给你一些双向边 求有多少个割点 并输出去掉点这个点 去掉后有几个联通分量
Tarjan
1 #include<stdio.h> 2 #include<algorithm> 3 #include<string.h> 4 #include<queue> 5 #include<math.h> 6 7 using namespace std; 8 9 #define MAXN 1000 10 int head[MAXN+10],dfn[MAXN+10],low[MAXN+10],z[MAXN+10]; 11 int cnt,num; 12 13 struct edg 14 { 15 int to,next; 16 17 }x[1000000]; 18 19 void add(int u,int v) 20 { 21 x[cnt].next=head[u]; 22 x[cnt].to=v; 23 head[u]=cnt++; 24 } 25 void dfs(int u,int k) 26 { 27 int i; 28 dfn[u]=low[u]=k; 29 for(i=head[u];i!=-1;i=x[i].next) 30 { 31 if(!dfn[x[i].to]) //没访问过 x[i].to孩子节点 32 { 33 dfs(x[i].to,k+1); 34 low[u]=min(low[u],low[x[i].to]); 35 if(low[x[i].to]>=dfn[u]) //不能跳过这个点 去掉后 必然多一个 36 z[u]++; 37 } 38 else 39 low[u]=min(low[u],dfn[x[i].to]); //访问过 x[i].to 是父亲节点 40 } 41 } 42 int main() 43 { 44 int n,m,ca,m1; 45 ca=1; 46 47 while(scanf("%d",&n)!=EOF&&n) 48 { 49 m1=0; 50 memset(head,-1,sizeof(head)); 51 memset(z,0,sizeof(z)); 52 memset(dfn,0,sizeof(dfn)); 53 memset(low,0,sizeof(low)); 54 scanf("%d",&m); 55 m1=max(n,m); 56 add(n,m),add(m,n); 57 58 int a,b; 59 while(scanf("%d",&a)!=EOF&&a) 60 { 61 scanf("%d",&b); 62 m1=max(m1,a); 63 m1=max(m1,b); 64 add(a,b),add(b,a); 65 } 66 dfs(1,1); /考虑 1 是根 数组搞出来要减1 67 z[1]--; 68 if(ca!=1) 69 printf("\n"); 70 printf("Network #%d\n",ca++); 71 int ok=0; 72 73 for(int i=1;i<=m1;i++) 74 { 75 if(z[i]>0) 76 { 77 printf(" SPF node %d leaves %d subnets\n",i,z[i]+1); 去掉该点以下的联通分量 上面还有一半 78 ok=1; 79 } 80 } 81 if(ok==0) 82 printf(" No SPF nodes\n"); 83 } 84 85 return 0; 86 } 87 /* 88 Network #1 89 SPF node 3 leaves 2 subnets 90 */
时间: 2024-10-01 00:31:51