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

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值