您的位置:首页 > 其它

[割点] poj 1523 SPF

2012-08-14 23:44 399 查看
/**
[割点] poj 1523 SPF
求割点及去掉该割点后的连通分量个数。
dfn[] dfs产生的优先数
low[u] 从u或u的子孙出发通过回边可以到达的最低深度优先数
low[u] = min{dfn[u], min{low[w]|w是u的一个子女}, min{dfn[v]|v与u邻接且(u,v)是一条回边} }
顶点u是割点的充要条件是: u 或者 是具有两个以上子女的深度优先生成树的根,
或者虽不是一个根,但他有一个子女w使得low[w] >= dfn[u]
*/
#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
using namespace std;

#define N 1001
vector<int> vec
;
int low
,dfn
,subnet
,vis
;
int cnt,son,n;

void dfs(int u)
{
for(int i = 0; i < vec[u].size(); ++i)
{
int v = vec[u][i];
if(!vis[v])
{
vis[v] = 1;
low[v] = dfn[v] = ++cnt;
dfs(v);
low[u] = min(low[v],low[u]);
if(low[v] >=dfn[u])
{
if(u == n)
++son;
else
++subnet[u];
}
}
else
low[u] = min(low[u],dfn[v]);
}
}
void cutPoint()
{
memset(subnet,0,sizeof(subnet));
memset(vis,0,sizeof(vis));
dfn
= low
= vis
= 1;
cnt = 1;
son = 0;
dfs(n);
if(son > 1)
subnet
= son - 1;
//if subnet[i] != 0 则i为割点且删除i后的连通分量个数为subnet[i] + 1
for(int i = 1; i <= n; ++i)
vec[i].clear();
}
int main()
{
int a,b,cas = 0;
while(scanf("%d",&a) && a)
{
n = a;
scanf("%d",&b);
n = max(n,b);
vec[a].push_back(b);
vec[b].push_back(a);
while(scanf("%d",&a) && a)
{
scanf("%d",&b);
n = max(a,n);
n = max(b,n);
vec[a].push_back(b);
vec[b].push_back(a);
}
cutPoint();
printf("Network #%d\n",++cas);
int i,find = 0;
for(i = 1; i <= n; ++i)
if(subnet[i])
{
find = 1;
printf("  SPF node %d leaves %d subnets\n",i,subnet[i] + 1);
}
if(!find)
printf("  No SPF nodes\n");
puts("");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: