您的位置:首页 > 其它

POJ 1523 SPF (割顶 点双连通分量)

2015-05-16 20:13 645 查看
题意就是求出在一个图上去除一个点之后,那个图会变成多少个子连通图。

显然我们要求出割顶。我的代码套用了刘汝佳的大白书的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");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: