POJ 1523 SPF (割顶 点双连通分量)
2015-05-16 20:13
645 查看
题意就是求出在一个图上去除一个点之后,那个图会变成多少个子连通图。
显然我们要求出割顶。我的代码套用了刘汝佳的大白书的tarjan算法,用一个数组cnt[]记录一个点是多少个点双连通分量的割顶。当发现一个点是割顶的时候,就cnt[i]++。最后,如果一个点是一棵dfs树的树根时,就输出cnt[i],否则就输出cnt[i]+1(因为那个点有父亲,而cnt数组记录的相当于是该点的儿子个数)。
显然我们要求出割顶。我的代码套用了刘汝佳的大白书的tarjan算法,用一个数组cnt[]记录一个点是多少个点双连通分量的割顶。当发现一个点是割顶的时候,就cnt[i]++。最后,如果一个点是一棵dfs树的树根时,就输出cnt[i],否则就输出cnt[i]+1(因为那个点有父亲,而cnt数组记录的相当于是该点的儿子个数)。
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<queue> #include<set> #include<vector> #include<climits> #include<stack> using namespace std; struct Edge { int u,v; Edge(int uu,int vv) { u=uu;v=vv; } Edge(){} }; const int maxn=1005; int pre[maxn],iscut[maxn],bccno[maxn],dfs_clock,bcc_cnt; vector<int>G[maxn],bcc[maxn]; vector<pair<int,int> > ans; int cnt[maxn]; bool isfa[maxn]; stack<Edge>s; int dfs(int u,int fa) { int lowu=pre[u]=++dfs_clock; int child=0; for(int i=0;i<G[u].size();i++) { int v=G[u][i]; Edge e=Edge(u,v); if(!pre[v]) { s.push(e); child++; int lowv=dfs(v,u); lowu=min(lowu,lowv); if(lowv>=pre[u]) { iscut[u]=true;cnt[u]++; bcc_cnt++;bcc[bcc_cnt].clear(); for(;;) { Edge x=s.top();s.pop(); if(bccno[x.u]!=bcc_cnt){bcc[bcc_cnt].push_back(x.u);bccno[x.u]=bcc_cnt;} if(bccno[x.v]!=bcc_cnt){bcc[bcc_cnt].push_back(x.v);bccno[x.v]=bcc_cnt;} if(x.u==u&&x.v==v) break; } } } else if(pre[v]<pre[u]&&v!=fa) { s.push(e); lowu=min(lowu,pre[v]); } } if(fa<0) { isfa[u]=true; if(child==1) iscut[u]=false; } return lowu; } void find_bcc(int n) { memset(pre,0,sizeof(pre)); memset(iscut,0,sizeof(iscut)); memset(bccno,0,sizeof(bccno)); memset(isfa,0,sizeof(isfa)); dfs_clock=bcc_cnt=0; for(int i=0;i<n;i++) if(!pre[i]) dfs(i,-1); } int main() { int u,v; bool flag=true; int cas=0; while(flag) { int maxed=-1; for(int i=0;i<=1000;i++) G[i].clear(); memset(cnt,0,sizeof(cnt)); ans.clear(); bool valid=false; while(1) { if(scanf("%d",&u)!=EOF) { if(0==u) break; if(u>maxed) maxed=u; scanf("%d",&v); if(v>maxed) maxed=v; valid=true; u--,v--; G[u].push_back(v); G[v].push_back(u); } else {flag=false;break;} } if(!flag) break; if(valid==false) break; find_bcc(maxed); bool hascut=false; for(int i=0;i<maxed;i++) { if(iscut[i]) { hascut=true; if(!isfa[i])ans.push_back(make_pair(i+1,cnt[i]+1)); else ans.push_back(make_pair(i+1,cnt[i])); } } cas++; printf("Network #%d\n",cas); if(!hascut) printf(" No SPF nodes\n"); else { for(int i=0;i<ans.size();i++) { printf(" SPF node %d leaves %d subnets\n",ans[i].first,ans[i].second); } } printf("\n"); } }
相关文章推荐
- POJ1523 SPF【点双连通分量】【Tarjan】
- POJ 1523 SPF (割点 && 点双连通分量)
- POJ 1523 SPF【双连通分量_割点】
- POJ 1523 SPF (割点 && 点双连通分量)
- poj_1523 SPF(求割顶)
- poj 1523 SPF(双连通分量割点模板)
- POJ 1523 SPF 点双连通分量
- POJ 1523 SPF
- POJ 1523 SPF
- SPF(poj 1523) 割点入门
- poj1523 SPF
- POJ 1523 SPF
- Zoj 1119 POJ 1523 SPF 求关节点及删除关节点会出现多少个连通分量 Tarjan算法
- POJ 1523 SPF tarjan求割点模板
- 无向图的割顶(poj1523,1144)
- POJ1523 SPF(割点模板)
- POJ1523 SPF
- POJ 1523、ZOJ 1119 SPF - from lanshui_Yang
- POJ 1523--SPF【无向图的所有割点 && 删去该点后bcc的数目】
- POJ - 1523 SPF