SPF POJ - 1523 割点+并查集
题意:
问你这个图中哪个点是割点,如果把这个点去掉会有几个子网
代码:
1 //给你几个点,用着几个点形成了一个图。输入边形成的图,问你这个图中有多少个割点。每一个割点去掉后会形成几个强连通分量 2 //方法: 3 //你可以想用tarjan算法求出来谁是割点。然后每一个割点单独用并查集判断。用所有边(不和这个割点相连的边)通过并查集判断一下 4 //然合并后有几个区域就可以了 5 #include<stdio.h> 6 #include<string.h> 7 #include<algorithm> 8 using namespace std; 9 const int spot=1010; 10 const int edge=500010; 11 struct node 12 { 13 int u,v; 14 }m[edge]; 15 struct stu 16 { 17 int to,next; 18 } a[edge]; 19 int head[spot],fa,low[spot],num[spot],root,indexx,sizes,flag1,n,fx[spot],qua,len,v[spot]; //fx指祖节点 20 bool flag[spot],flag2[spot],b[spot],have[spot]; 21 void init() 22 { 23 indexx=0,sizes=0,flag1=1,n=0; 24 len=qua=0; 25 memset(head,-1,sizeof(head)); 26 memset(low,0,sizeof(low)); 27 memset(num,0,sizeof(num)); 28 memset(flag,0,sizeof(flag)); 29 memset(have,0,sizeof(have)); 30 } 31 void add_edge(int from,int to) //并查集 32 { 33 a[sizes].to=to; 34 a[sizes].next=head[from]; 35 head[from]=sizes++; 36 a[sizes].to=from; 37 a[sizes].next=head[to]; 38 head[to]=sizes++; 39 n=max(n,from); 40 n=max(n,to); 41 m[len].u=from; 42 m[len++].v=to; 43 } 44 void dfs(int cur) //求割点 45 { 46 int child=0; 47 num[cur]=++indexx; 48 low[cur]=indexx; 49 int k,v; 50 for(k=head[cur]; k+1; k=a[k].next) 51 { 52 v=a[k].to; 53 if(!num[v]) 54 { 55 dfs(v); 56 low[cur]=min(low[cur],low[v]); 57 if(low[v]>=num[cur]) 58 { 59 child++; 60 if(cur!=fa || child>1) flag[cur]=1,qua++; 61 } 62 } 63 else 64 low[cur]=min(low[cur],num[v]); 65 } 66 } 67 int finds(int x) 68 { 69 if(x!=v[x]) 70 { 71 int y=finds(v[x]); 72 return v[x]=y; 73 } 74 return x; 75 } 76 int panduan(int x) 77 { 78 for(int i=1;i<=n;++i) 79 { 80 if(have[i]) v[i]=i; 81 } 82 for(int i=0;i<len;++i) 83 { 84 if(m[i].u!=x && m[i].v!=x) 85 { 86 int fx=finds(m[i].u); 87 int fy=finds(m[i].v); 88 if(fx!=fy) v[fx]=fy; 89 } 90 } 91 int ans=0; 92 for(int i=1;i<=n;++i) 93 { 94 if(i!=x && v[i]==i) ++ans; 95 } 96 return ans; 97 } 98 int main() 99 { 100 int x,y,i,ss=0,ans,j; 101 while(scanf("%d",&x)&&x) 102 { 103 init(); 104 scanf("%d",&y); 105 root=x; 106 have[x]=1; 107 have[y]=1; 108 add_edge(x,y); 109 for(;;) 110 { 111 scanf("%d",&x); 112 if(!x) break; 113 scanf("%d",&y); 114 add_edge(x,y); 115 have[x]=1,have[y]=1; 116 } 117 fa=root; 118 dfs(root); 119 printf("Network #%d\n",++ss); 120 for(i=1; i<=n; i++) 121 { 122 if(flag[i]) 123 { 124 flag1=0; 125 int q=panduan(i); 126 printf(" SPF node %d leaves %d subnets\n",i,q); 127 } 128 } 129 if(flag1) 130 printf(" No SPF nodes\n"); 131 printf("\n"); 132 } 133 return 0; 134 }