题意:
给个无向图,问有多少个割点,对于每个割点求删除这个点之后会产生多少新的点双联通分量
题还是很果的
怎么求割点请参考tarjan无向图
关于能产生几个新的双联通分量,对于每个节点u来说,我们判断他是否是割点,即判断是否满足他的儿子v的low[v]>dfn[u]
而这个时候割掉这个点就会让双联通分量增加,所以搞一个数组记录一下这个操作的次数就行
请注意在是否是根节点的问题上特判
!!注意输出格式!!
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define N 5010 5 #define M 10100 6 #define Max(a,b,c) max(max(a,b),c) 7 using namespace std; 8 int head[N],n,m,ecnt=2,u,v,dfn[N],low[N],indx,du[N],ans,isap[N],ap,task,sum[N]; 9 struct edge 10 { 11 int u,v,nxt; 12 }e[M*2]; 13 void add(int u,int v) 14 { 15 e[ecnt].v=v; 16 e[ecnt].nxt=head[u]; 17 e[ecnt].u=u; 18 head[u]=ecnt++; 19 e[ecnt].v=u; 20 e[ecnt].nxt=head[v]; 21 e[ecnt].u=v; 22 head[v]=ecnt++; 23 } 24 void dfs(int u,int fa) 25 { 26 dfn[u]=low[u]=++indx; 27 int n_ch=0; 28 for (int i=head[u];i;i=e[i].nxt) 29 { 30 int v=e[i].v; 31 if (!dfn[v]) 32 { 33 dfs(v,i); 34 low[u]=min(low[u],low[v]); 35 if (low[v]>=dfn[u]) 36 isap[u]=1,ap++,sum[u]++; 37 n_ch++; 38 } 39 else 40 if (v!=fa) 41 low[u]=min(dfn[v],low[u]); 42 } 43 if (fa==-1 && n_ch==1) 44 isap[u]=0,ap--; 45 if (isap[u] && fa!=-1) sum[u]++; 46 } 47 void init() 48 { 49 n=0; 50 memset(sum,0,sizeof(sum)); 51 memset(head,0,sizeof(head)); 52 memset(dfn,0,sizeof(dfn)); 53 memset(isap,0,sizeof(isap)); 54 ecnt=2; 55 ans=0; 56 indx=0; 57 ap=0; 58 } 59 void solve() 60 { 61 if (n==0) return; 62 task++; 63 for (int i=1;i<=n;i++) 64 if (!dfn[i]) dfs(i,-1); 65 printf("Network #%d ",task); 66 if (ap==0) 67 printf(" No SPF nodes "); 68 for (int i=1;i<=n;i++) 69 if (isap[i]) 70 printf(" SPF node %d leaves %d subnets ",i,sum[i]); 71 putchar(' '); 72 init(); 73 } 74 int main() 75 { 76 // freopen("1.in","r",stdin); 77 while (1) 78 { 79 while (scanf("%d",&u)!=EOF) 80 { 81 if (u==0) 82 { 83 solve(); 84 continue; 85 } 86 if (scanf("%d",&v)==EOF) break; 87 n=Max(n,u,v); 88 add(u,v); 89 // printf("%d %d ",u,v); 90 } 91 if (n==0) break; 92 } 93 return 0; 94 }