POJ1144 Network
http://poj.org/problem?id=1144
题意
给出一个无向图,求出有多少个割点。
输入
有若干组测试数据。每一组测试数据的第一行有一个整数 n,表示有 n(1<=n<100)个点,n=0 时测试数据结束。接下来有若干行,每一行第一个整数 u 表示这一行描述的是以 u 为起点的边,接下来有若干个整数 vi 表示有一条边 u-vi,u=0 时表示这一组测试数据结束。
输出
对于每一组测试数据,输出一个整数,即有多少个割点。
样例输入
5
5 1 2 3 4
0
6
2 1 3
5 4 6 2
0
0
样例输出
1
2
分析
Tarjan算法
C++程序
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N=105;
bool flag[N];//标记每个点是否为割点
int dfn[N],low[N],pre[N];
int index,n;
vector<int>g[N];
void Tarjan(int u,int father)
{
pre[u]=father;
dfn[u]=low[u]=index++;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(!dfn[v])
{
Tarjan(v,u);
low[u]=min(low[u],low[v]);
}
else if(v!=father)//连回到父节点的回边不考虑,否则求不出桥
low[u]=min(low[u],dfn[v]);
}
}
//计算割点
void solve()
{
int num=0;
for(int i=0;i<=n;i++)
dfn[i]=low[i]=pre[i]=flag[i]=0;
index=0;
Tarjan(1,0);
for(int i=2;i<=n;i++)
{
int v=pre[i];
if(v==1)
num++;//DFS树中根节点有几个子树
else if(dfn[v]<=low[i])
flag[v]=true;
}
if(num>1)
flag[1]=true;
//统计割点的个数
int ans=0;
for(int i=1;i<=n;i++)
if(flag[i])
ans++;
printf("%d\n",ans);
}
int main()
{
while(scanf("%d",&n)&&n)
{
for(int i=0;i<=n;i++)
g[i].clear();
int u,num,v;
while(scanf("%d",&u)&&u)
{
while(getchar()!='\n')
{
scanf("%d",&v);
g[u].push_back(v);
g[v].push_back(u);
}
}
solve();
}
return 0;
}
本文详细解析了POJ1144 Network题目,利用Tarjan算法求解无向图中的割点数量。通过深度优先搜索和低点值计算,有效地找出所有割点,并附带完整C++代码实现。
239

被折叠的 条评论
为什么被折叠?



