大致题意:
给出一个连通的无向图,求哪些点是割点,对于每个割点,求出去掉这个点后连通分量的个数。如果没有割点的话输出“ No SPF nodes”。
思路:
求割点用tarjan即可,然后要求删除割点后连通分量的个数,每次找到割点,再在从割点dfs即可,也可以直接在tarjan算法中记录child个数。那么如果割点是根,那么答案就是child,不是根的割点答案是child+1
//188K 0MS C++ 2121B #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int N = 1010; int head[N]; struct Edge { int v,next; }es[N*N]; struct node { int u; int cnt; }ans[N]; int n; int cnt; int dfn[N],low[N]; int index,top=0; bool vis[N]; bool book[N]; void tarjan(int u,int rt,int pa) { dfn[u]=low[u]=++index; int child=0; for(int i=head[u];~i;i=es[i].next) { int v=es[i].v; if(dfn[v]==0) { tarjan(v,rt,u); low[u]=min(dfn[u],low[v]); if(low[v]>=dfn[u]) child++; } if(v!=pa) low[u]=min(dfn[u],low[v]); } if(u==rt&&child>1) ans[++top].u=u,ans[top].cnt=child; else if(u!=rt&&child) ans[++top].u=u,ans[top].cnt=child+1; } void ini() { memset(head,-1,sizeof(head)); cnt=0; n=-1; memset(dfn,0,sizeof(dfn)); memset(book,0,sizeof(book)); top=index=0; } bool cmp(const node &a,const node&b) { return a.u<b.u; } int main() { int u,v; int cas=0; while(scanf("%d%d",&u,&v)== 2) { printf("Network #%d\n",++cas); ini(); n=max(n,u); n=max(v,n); es[++cnt].v=v; es[cnt].next=head[u]; head[u]=cnt; es[++cnt].v=u; es[cnt].next=head[v]; head[v]=cnt; while(1) { scanf("%d",&u); if(u==0) break; scanf("%d",&v); es[++cnt].v=v; es[cnt].next=head[u]; head[u]=cnt; es[++cnt].v=u; es[cnt].next=head[v]; head[v]=cnt; n=max(max(u,v),n); } for(int i=1;i<=n;i++) if(dfn[i]==0) tarjan(i,i,-1); sort(ans+1,ans+1+top,cmp); if(top==0) printf(" No SPF nodes\n"); for(int i=1;i<=top;i++) { printf(" SPF node %d leaves %d subnets\n",ans[i].u,ans[i].cnt); } puts(""); } return 0; }
时间: 2024-11-13 20:07:26