UVALive 6044(双连通分量的应用)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34902

思路:首先是双连通缩点,然后就是搜索一下,搜索时要跳过连通分量的点的个数>=2的点,最后的答案是n*(n-1)/2.

  1 #include<iostream>

  2 #include<cstdio>

  3 #include<cstring>

  4 #include<algorithm>

  5 #include<stack>

  6 #include<vector>

  7 using namespace std;

  8 #define MAXN 11111

  9 #define MAXM 444444

 10 

 11 struct Edge{

 12     int v,next;

 13 }edge[MAXM];

 14 

 15 int n,m,NE,cnt,_count;

 16 int head[MAXN];

 17 

 18 void Insert(int u,int v)

 19 {

 20     edge[NE].v=v;

 21     edge[NE].next=head[u];

 22     head[u]=NE++;

 23 }

 24 

 25 int low[MAXN],dfn[MAXN];

 26 int color[MAXN];

 27 bool mark[MAXN];

 28 stack<int>S;

 29 void Tarjan(int u,int father)

 30 {

 31     int flag=0;

 32     low[u]=dfn[u]=++cnt;

 33     mark[u]=true;

 34     S.push(u);

 35     for(int i=head[u];i!=-1;i=edge[i].next){

 36         int v=edge[i].v;

 37         if(v==father&&!flag){ flag=1;continue; }

 38         if(dfn[v]==0){

 39             Tarjan(v,u);

 40             low[u]=min(low[u],low[v]);

 41         }else if(mark[v]){

 42             low[u]=min(low[u],dfn[v]);

 43         }

 44     }

 45     if(low[u]==dfn[u]){

 46         _count++;

 47         int x=S.top();

 48         if(x==u)S.pop();

 49         else {

 50             do{

 51                 x=S.top();

 52                 S.pop();

 53                 mark[x]=false;

 54                 color[x]=_count;

 55             }while(x!=u);

 56         }

 57     }

 58 }

 59 

 60 int ans;

 61 void dfs(int u,int father)

 62 {

 63     color[u]=1;

 64     _count++;

 65     for(int i=head[u];i!=-1;i=edge[i].next){

 66         int v=edge[i].v;

 67         if(v==father)continue;

 68         if(color[v])continue;

 69         dfs(v,u);

 70     }

 71 }

 72 

 73 

 74 int main()

 75 {

 76     int _case,u,v,t=1;

 77     scanf("%d",&_case);

 78     while(_case--){

 79         scanf("%d%d",&n,&m);

 80         NE=0;

 81         memset(head,-1,sizeof(head));

 82         while(m--){

 83             scanf("%d%d",&u,&v);

 84             Insert(u,v);

 85             Insert(v,u);

 86         }

 87         cnt=_count=0;

 88         memset(dfn,0,sizeof(dfn));

 89         memset(color,0,sizeof(color));

 90         for(int i=1;i<=n;i++){

 91             if(dfn[i]==0)Tarjan(i,-1);

 92         }

 93         ans=0;

 94         for(int i=1;i<=n;i++){

 95             if(color[i]==0){

 96                 _count=0;

 97                 dfs(i,-1);

 98                 ans+=_count*(_count-1)/2;

 99             }

100         }

101         printf("Case #%d: %d\n",t++,ans);

102     }

103     return 0;

104 }

105 

106 

107 

108         
View Code

 

 

你可能感兴趣的:(live)