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