您的位置:首页 > 其它

无重边无向连通图的割点和桥

2016-05-17 11:15 267 查看
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
vector<vector<int> > g;
int dfn[11000];//节点在dfs过程中的访问序号(也可以叫做开始时间)
int low[11000];//节点的子树中能够通过非父子边追溯到的最早的节点的dfs开始时间
int fa[11000];//dfs树中每个点的父节点
int viscv[11000];//标记是否为割点
int ntime;//dfs中记录时间
int n,m;//点数和边数
void tarjan(int u,int father)//father是u的父节点
{
fa[u]=father;
int i;
low[u]=dfn[u]=ntime++;
for(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(father!=v)
{
low[u]=min(low[u],dfn[v]);
}
}
}
void solve()
{
int sontree=0;//dfs树中根节点的子树的数目
int i;
tarjan(1,0);
for(i=2;i<=n;i++)
{
int v=fa[i];
if(v==1) sontree++;
else
{
if(dfn[v]<=low[i])
viscv[v]=1;
}
}
if(sontree>1) viscv[1]=1;
for(i=1;i<=n;i++)
{
if(viscv[i])
printf("%d\n",i);
}
for(i=1;i<=n;i++)
{
int v=fa[i];
if(v>0&&dfn[v]<low[i])
printf("%d %d\n",v,i);
}
}
int main()
{
int u,v,i;
ntime=1;
while(scanf("%d%d",&n,&m)!=EOF)
{
g.clear();
g.resize(11000);
ntime=1;
for(i=0;i<m;i++)//点编号是从1开始的
{
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(fa,0,sizeof(fa));
memset(viscv,0,sizeof(viscv));
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: