poj 1523求割点
题意:给出一个无向图,求割点以及去除这个点后图分为几部分;
思路:割点定义:去掉该点后图将分成几个部分。割点:(1)当k为根节点且有>1个分支,则去除该点后图便被分成几个分支。(2)DFN[v]<Low[j]表示v的子节点不会有回路回到v的祖先。
代码:
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define MAXN 1005 #define MAXM 1005*1005 struct Edge { int to,next; }edge[MAXM]; int Low[MAXN],DFN[MAXN],first[MAXN],son,vis[MAXN]; int n,count,cut[MAXN],tot,root; void addedge(int v,int w) { edge[tot].to=w; edge[tot].next=first[v]; first[v]=tot++; } void Tarjan(int v) { DFN[v]=Low[v]=++count; for(int i=first[v];i!=-1;i=edge[i].next) { int j=edge[i].to; if(!DFN[j]) { Tarjan(j); if(root==v) { son++; if(son>1) cut[v]=1; } else { Low[v]=min(Low[j],Low[v]); if(DFN[v]<=Low[j])cut[v]=1; } } else { Low[v]=min(Low[v],DFN[j]); } } } void dfs(int u) { vis[u]=1; for(int i=first[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(!vis[v]) { dfs(v); } } } int main() { int x,y,t=0; while(scanf("%d",&x),x) { t++; memset(DFN,0,sizeof(DFN)); memset(first,-1,sizeof(first)); memset(Low,0,sizeof(Low)); memset(cut,0,sizeof(cut)); n=0; scanf("%d",&y); addedge(x,y); addedge(y,x); n=max(x,y); count=0; while(scanf("%d",&x),x) { scanf("%d",&y); addedge(x,y); addedge(y,x); n=max(x,y); } son=0; root=1; Tarjan(1); printf("Network #%d\n",t);//cout<<1111<<endl; int ans=0; int flag=0; for(int i=1;i<=n;i++) { if(cut[i]==1) { flag=1; memset(vis,0,sizeof(vis)); vis[i]=1; int son1=0; for(int j=first[i];j!=-1;j=edge[j].next) { int k=edge[j].to; if(!vis[k]) { dfs(k); son1++; } } printf(" SPF node %d leaves %d subnets\n",i,son1); } } if(!flag) printf(" No SPF nodes\n"); printf("\n"); } return 0; }