标签:
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 7406 | Accepted: 3363 |
Description
Input
Output
Sample Input
1 2 5 4 3 1 3 2 3 4 3 5 0 1 2 2 3 3 4 4 5 5 1 0 1 2 2 3 3 4 4 6 6 3 2 5 5 1 0 0
Sample Output
Network #1 SPF node 3 leaves 2 subnets Network #2 No SPF nodes Network #3 SPF node 2 leaves 2 subnets SPF node 3 leaves 2 subnets
题意:问将某个点删除可产生多少个连通分量。
思路:考察对tarjan算法原理理解,解释见代码。
#include"cstdio" #include"cstring" using namespace std; const int MAXN=1005; struct Edge{ int to,next; }es[MAXN*2]; int V,E; int head[MAXN]; inline int max(int u,int v) { return u > v? u: v; } inline int min(int a,int b) { return a > b? b: a; } void add_edge(int u,int v) { es[E].to=v; es[E].next=head[u]; head[u]=E++; V=max(max(u,v),V); } bool flag; int root; int subnets[MAXN]; int index; int dfn[MAXN],low[MAXN]; void tarjan(int u,int fa) { int son=0; dfn[u]=low[u]=++index; for(int i=head[u];i!=-1;i=es[i].next) { int v=es[i].to; if(!dfn[v]) { tarjan(v,u); son++; low[u]=min(low[u],low[v]); if((u==root&&son>1)||(u!=root&&dfn[u]<=low[v])) { flag=true; subnets[u]++; //u->v 该边导致u成为割点 //当dfn[u]==low[v]时u->v为返祖边,u、v处于同一双连通分量中 //当dfn[u]<low[v]时u->v为割边 //删除割点u产生的连通数目为:u所在的连通分量数目+与u所连接的割边的数目+1(边:fa->u) } } else if(v!=fa) low[u]=min(low[u],dfn[v]); } } int main() { int cas=0; int u,v; while(true) { v=-1; index=0; memset(subnets,0,sizeof(subnets)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(head,-1,sizeof(head)); V=-1,E=0; flag=false; while(scanf("%d",&u)&&u) { scanf("%d",&v); add_edge(u,v); add_edge(v,u); } if(v==-1) break; root=V; tarjan(root,-1); printf("Network #%d\n",++cas); if(flag) { for(int i=1;i<=V;i++) { if(subnets[i]>0) { printf(" SPF node %d leaves %d subnets\n",i,subnets[i]+1);//加上fa->u该边所连接的连通分量 } } } else printf(" No SPF nodes\n"); printf("\n"); } return 0; }
标签:
原文地址:http://www.cnblogs.com/program-ccc/p/5167506.html