题目链接:http://poj.org/problem?id=1523
题意:给出无向图的若干条边,求割点以及各个删掉其中一个割点后将图分为几块。
题目分析:割点用tarjan算法求出来,对于每个割点,dfs一次图,求出有几块不连通的子图。
AC代码:
1 #include<cstdio> 2 #include<cstring> 3 const int N=1000+5; 4 struct EDGE{ 5 int v,next; 6 }edge[N*N/2]; 7 int first[N],low[N],dfn[N],cut[N],vis[N]; 8 int g,ans,rt,son,cnt,sum; 9 int min(int a,int b) 10 { 11 return a<b?a:b; 12 } 13 int max(int a,int b) 14 { 15 return a>b?a:b; 16 } 17 void AddEdge(int u,int v) 18 { 19 edge[g].v=v; 20 edge[g].next=first[u]; 21 first[u]=g++; 22 } 23 void Tarjan(int u) 24 { 25 int i,v; 26 low[u]=dfn[u]=++cnt; 27 for(i=first[u];i!=-1;i=edge[i].next) 28 { 29 v=edge[i].v; 30 if(!dfn[v]) 31 { 32 Tarjan(v); 33 low[u]=min(low[u],low[v]); 34 if(u==rt) 35 son++; 36 else 37 { 38 if(low[v]>=dfn[u]) 39 cut[u]=true; 40 } 41 } 42 else 43 low[u]=min(low[u],dfn[v]); 44 } 45 } 46 void dfs(int u) 47 { 48 vis[u]=1; 49 for(int i=first[u];i!=-1;i=edge[i].next) 50 { 51 int v=edge[i].v; 52 if(!vis[v]) 53 dfs(v); 54 } 55 } 56 int main() 57 { 58 int t=0,u,v,n,i,p; 59 while(scanf("%d",&u)&&u) 60 { 61 t++; 62 n=-1; 63 memset(first,-1,sizeof(first)); 64 memset(cut,false,sizeof(cut)); 65 memset(dfn,0,sizeof(dfn)); 66 g=cnt=sum=0; 67 n=max(n,u); 68 scanf("%d",&v); 69 n=max(n,v); 70 AddEdge(u,v); 71 AddEdge(v,u); 72 while(scanf("%d",&u)&&u) 73 { 74 scanf("%d",&v); 75 n=max(n,u); 76 n=max(n,v); 77 AddEdge(u,v); 78 AddEdge(v,u); 79 } 80 for(i=1;i<=n;i++) 81 { 82 if(!dfn[i]) 83 { 84 rt=i; 85 son=0; 86 Tarjan(i); 87 if(son>1) 88 cut[rt]=true; 89 } 90 } 91 printf("Network #%d\n",t); 92 for(i=1;i<=n;i++) 93 { 94 if(cut[i]) 95 { 96 sum++; 97 ans=0; 98 memset(vis,0,sizeof(vis)); 99 vis[i]=1; 100 for(p=first[i];p!=-1;p=edge[p].next) 101 { 102 v=edge[p].v; 103 if(!vis[v]) 104 { 105 dfs(v); 106 ans++; 107 } 108 } 109 printf(" SPF node %d leaves %d subnets\n",i,ans); 110 } 111 } 112 if(sum==0) 113 printf(" No SPF nodes\n"); 114 printf("\n"); 115 } 116 return 0; 117 }