题目描述
在双向的通信网络中,若一台交换机受损可以使其他交换机的通信受到影响,则称这台交换机为灾区,给出通信网络,求出通信网络中灾区的数量。
思路
题目实际上就是让我们就图中割点的数目。对于tarjan的点,若这点为树根且子树不为1,那么它就是割点;若这个点不为树根且dfn[u]≤low[v],意味着v无法通过其他点到达搜索树上的其他点,那么这棵搜索树以下形成一个点双联通分量,u也是割点。
代码
#include <bits/stdc++.h> using namespace std; const int N=110,M=N*N; int nxt[M],to[M],tot,head[N]; void add_edge(int x,int y) { nxt[++tot]=head[x]; head[x]=tot; to[tot]=y; } bool f; int read() { int res=0,w=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+ch-'0';ch=getchar();} if(ch==' ')f=1; return res*w; } int dfn[N],low[N],idx,root; bool cut[N]; void tarjan(int u) { dfn[u]=low[u]=++idx; int cnt=0; for(int i=head[u];i;i=nxt[i]) { int v=to[i]; if(!dfn[v]) { cnt++; tarjan(v); low[u]=min(low[u],low[v]); if((root==u&&cnt>1)||(root!=u&&dfn[u]<=low[v])) cut[u]=1; } else low[u]=min(low[u],dfn[v]); } } void clear() { memset(head,0,sizeof(head)); memset(cut,0,sizeof(cut)); memset(dfn,0,sizeof(dfn)); tot=0;idx=0; } int main() { int n; while(n=read()) { clear(); if(n==0)break ; int x,y; while(x=read()) { if(x==0)break ; // cout<<x<<':'<<endl; f=0; while(y=read()) { // cout<<y<<endl; add_edge(x,y);add_edge(y,x); if(f)break ; } } for(int i=1;i<=n;i++) if(!dfn[i]) { root=i; tarjan(i); } int sum=0; for(int i=1;i<=n;i++) if(cut[i])sum++; printf("%d ",sum); } }