点双

  void dfs1(int po,int fa){
      dfn[po]=low[po]=++cnt;
      int degcnt=0,flag=0;
      for (int p=a.nd[po];p!=-1;p=a.next[p])
        if (!dfn[a.des[p]]){
            degcnt++;sta[++top]=a.id[p];
          dfs1(a.des[p],po);
          low[po]=min(low[po],low[a.des[p]]);
        if (low[a.des[p]]>=dfn[po]){
          flag=1;
          idcnt++;
          while (1){
            int t=sta[top--];
            belo[t]=idcnt;
            if (t==a.id[p]) break;
          }    
        }
      }else{
          if (dfn[a.des[p]]<dfn[po]&&a.des[p]!=fa){
            low[po]=min(low[po],dfn[a.des[p]]);    
            sta[++top]=a.id[p];
        }
      }
      
    if (fa&&flag) bri[po]=1;
    if ((!fa)&&degcnt>=2) bri[po]=1;
  }

 ---------------------------------------------------------------------------------------------------

现在有n个通讯基站(从1-n标号),有m对通讯基站之间可以进行直接的互相通讯,保证任意两个通讯基站都能直接或者间接通讯。对于两个不同的通讯基站A和B,如果他们之间的通讯信息必然会经过C(可以为A或者B),那么我们说C是A、B通讯的必经点,显然会有多个必经点。对于任意一个点C可能有多对不同的(A,B)满足C是A、B通讯的必经点。((A,B)和(B,A)只算一对)。
鸡腿的任务是找到一个通讯基站C是最多对通讯基站的通讯必经点。
鸡腿很懒,所以这个任务就交给你了。你需要告诉鸡腿,每一个通讯基站分别是多少对不同的通讯基站的必经点。

建圆方树

#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <utility>
#define LL long long 
using namespace std;

  struct graph{
      int nd[500001],nxt[500001],des[500001],id[500001],cnt;
      
      void addedge(int x,int y,int po){
        nxt[++cnt]=nd[x];des[cnt]=y;id[cnt]=po;nd[x]=cnt;
        nxt[++cnt]=nd[y];des[cnt]=x;id[cnt]=po;nd[y]=cnt;
    }
      
      void init(){
        memset(nd,-1,sizeof(nd));
    }
  }a,b;

  map <int,int> mp[500001];
  map <pair<int,int> ,int>added; 
  int dfn[500001],low[500001],cnt,sta[500001],top,idcnt,belo[500001];
  int n,size[500001],m,sid[500001][2];
  LL ans[500001];

  void dfs1(int po,int fa){
      dfn[po]=low[po]=++cnt;
      int degcnt=0,flag=0;
      for (int p=a.nd[po];p!=-1;p=a.nxt[p])
        if (!dfn[a.des[p]]){
          degcnt++;sta[++top]=a.id[p];
          dfs1(a.des[p],po);
          low[po]=min(low[po],low[a.des[p]]);
        if (low[a.des[p]]>=dfn[po]){
          flag=1;
          idcnt++;
          while (1){
            int t=sta[top--];
            belo[t]=idcnt;
            if (t==a.id[p]) break;
          }    
        }
      }else{
        if (dfn[a.des[p]]<dfn[po]&&a.des[p]!=fa){
          low[po]=min(low[po],dfn[a.des[p]]);    
          sta[++top]=a.id[p];
        }
      }
  }
  
  void dfs2(int po,int fa){
      LL tot=0,sum=0;
      if (po<=n) sum=1;else sum=0;
      for (int p=b.nd[po];p!=-1;p=b.nxt[p])
        if (b.des[p]!=fa){
          dfs2(b.des[p],po);
          tot+=sum*size[b.des[p]];
          sum+=size[b.des[p]];
      }
      size[po]=sum;  
      if (po<=n)
        ans[po]=tot+sum*(n-sum);
  }
  
  int main(){
      scanf("%d%d",&n,&m);
      a.init();b.init();
      for (int i=1;i<=m;i++){
        scanf("%d%d",&sid[i][0],&sid[i][1]);
        if (sid[i][0]>sid[i][1]) swap(sid[i][0],sid[i][1]);
        if (sid[i][0]==sid[i][1]||added[make_pair(sid[i][0],sid[i][1])]) continue;
        added[make_pair(sid[i][0],sid[i][1])]=1;
        a.addedge(sid[i][0],sid[i][1],i);
    }
    
    dfs1(1,0);
    for (int i=1;i<=m;i++) if (belo[i]){
      if (!mp[belo[i]][sid[i][0]])
        b.addedge(belo[i]+n,sid[i][0],-1),mp[belo[i]][sid[i][0]]=1;    
      if (!mp[belo[i]][sid[i][1]])
        b.addedge(belo[i]+n,sid[i][1],-1),mp[belo[i]][sid[i][1]]=1;
    }
    dfs2(1,0);
    for (int i=1;i<=n;i++)
      printf("%lld\n",ans[i]);
  }

 

posted @ 2017-04-19 10:58  z1j1n1  阅读(298)  评论(0编辑  收藏  举报