//割边模板,邻接矩阵实现O(N^2),最好改为邻接表O(N+M)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
struct Edge
{
int u,v,next;
}e[101];
int first[101],cnt; //cnt:边的数量(编号)
int n,m,root;
int num[101],low[101],index=0; //index用来进行时间戳的递增;flag:标记割点
int x,y;
void addedge(int u,int v) //建立邻接表
{
e[cnt].u=u; e[cnt].v=v;
e[cnt].next=first[u];first[u]=cnt++;
}
void dfs(int cur,int father) //cur:当前顶点的编号;father:上一条边的编号
{
index++; //时间戳加1
num[cur]=index; //当前顶点cur的时间戳
low[cur]=index; //当前顶点cur能够访问到最早顶点的时间戳(刚开始当然是自己)
for(int i=first[cur];i!=-1;i=e[i].next) //枚举所有从当前顶点cur出发边i
{
if(num[e[i].v]==0) //如果第i条边终点v的时间戳为0,说明顶点v还没有被访问过
{ //点v为cur的儿子
dfs(e[i].v,i); //从cur的儿子v继续往下DFS
low[cur]=min(low[cur],low[e[i].v]); //更新当前顶点cur能访问到最早顶点的时间戳
if(low[e[i].v]>num[cur]) printf("%d-%d\n",cur,e[i].v); //满足low[v]>num[cur]),输出割边 cur-->v
}
else //如果点v曾经被访问过,并且v不是当前顶点cur的父亲,则说明此时的v为cur的祖先
if((i^1)!=father) low[cur]=min(low[cur],num[e[i].v]); //因此需要更新当前结点cur能访问到最早顶点的时间戳
}
return;
}
int main()
{
freopen("gebian.in","r",stdin);
freopen("gebian.out","w",stdout);
memset(first,-1,sizeof(first));
cnt=0; //边的数量(编号)
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++) //读入无向图的m条边
{
scanf("%d %d",&x,&y);
addedge(x,y); //建立邻接表
addedge(y,x); //反向建立邻接表
}
root=1; //设整个图的根为1
dfs(1,root); //从1号顶点开始DFS,root是1的父亲
return 0;
}
强连通-割边(曾老代码)
最新推荐文章于 2017-07-22 16:43:09 发布