题意很简单,求删除割点后原先割点所在的无向连通图被分成了几个连通部分(原题说prevent at least one pair of available nodes from being able to communicate on what was previously a fully connected network,阻止至少一对可用节点能够在先前完全连接的网络上进行通信,所以输入的图不保证连通)
对于每个割点
- 如果它是根节点,则答案=DFS树的子树数量
- 如果它是非根节点,则答案=孩子low值>=当前结点的dfn值的孩子数
注意要扫描所有的点从未访问的点开始DFS!
还有多组数据记得清空数组!
代码如下(我绝对不会告诉你们我因为写错了输出格式而调了一上午)
1 #include<cstdio> 2 #include<cctype> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 #define re register int 7 struct edge 8 { 9 int to,pre; 10 }edges[499501];//邻接表 11 int head[1001],tot,dfn[1001],dfs_clock; 12 int ans[1001];//删去结点i后连通分量的个数 13 int read() 14 { 15 int f=0,x=0; 16 char c=getchar(); 17 while(!isdigit(c)) 18 { 19 f=f|c=='-'; 20 c=getchar(); 21 } 22 while(isdigit(c)) 23 { 24 x=(x<<1)+(x<<3)+(c^48); 25 c=getchar(); 26 } 27 return x; 28 } 29 void add(int x,int y) 30 { 31 edges[++tot].to=y; 32 edges[tot].pre=head[x]; 33 head[x]=tot; 34 } 35 int tarjan(int u,int fa) 36 { 37 int lowu=dfn[u]=++dfs_clock,child=0; 38 ans[u]=1; 39 for(re i=head[u];i;i=edges[i].pre) 40 if(!dfn[edges[i].to]) 41 { 42 child++; 43 int lowv=tarjan(edges[i].to,u); 44 lowu=min(lowu,lowv); 45 if(lowv>=dfn[u])//有一个孩子满足,连通分量+1 46 ans[u]++; 47 } 48 else if(edges[i].to!=fa) 49 lowu=min(lowu,dfn[edges[i].to]); 50 if(u==fa)//根节点删去后连通分量数=子树个数 51 ans[u]=child; 52 return lowu; 53 } 54 int main() 55 { 56 int t=0,x,y; 57 while(x=read()) 58 { 59 memset(edges+1,0,499500<<3),memset(head+1,0,1000<<2),memset(dfn+1,0,1000<<2); 60 tot=dfs_clock=0; 61 t++; 62 y=read(); 63 int n=max(x,y); 64 add(x,y),add(y,x); 65 while(x=read()) 66 { 67 y=read(); 68 n=max(max(x,y),n); 69 add(x,y),add(y,x); 70 } 71 tarjan(1,1); 72 printf("Network #%d\n",t); 73 int pd=0; 74 for(re i=1;i<=n;i++) 75 if(ans[i]>1) 76 { 77 pd=1; 78 printf(" SPF node %d leaves %d subnets\n",i,ans[i]); 79 } 80 if(!pd) 81 printf(" No SPF nodes\n"); 82 printf("\n"); 83 } 84 return 0; 85 }