您的位置:首页 > 其它

点双联通分量模板

2017-08-07 14:23 393 查看
#include <bits/stdc++.h>

#define MAXN 10005

using namespace std;

struct Tarjan
{
struct edge
{
int u,v;
edge(int uu=0,int vv=0):u(uu),v(vv){}
bool operator ==(const edge &p)const
{
return (u==p.u&&v==p.v)||(v==p.u&&u==p.v);
}
};

int n;	//点的个数

vector<int> e[MAXN];	//图
int DFN[MAXN],LOW[MAXN];
int index;	//编号计数器

edge stk[MAXN];	//栈
int top;

vector<vector<edge> > Ans;	//记录答案
bool iscut[MAXN];	//记录点是否为割点

void init(int N)	//初始化
{
n=N;

Ans.clear();
for(int i=1;i<=n;i++)
e[i].clear();
top=0;
index=0;

memset(DFN,-1,sizeof(DFN));
memset(iscut,0,sizeof(iscut));
}

void AddEdge(int u,int v)	//添加边
{
e[u].push_back(v);
e[v].push_back(u);
}

void DFS(int u,int prt)	//从点u开始搜索
{
DFN[u]=LOW[u]=++index;

int child=0;

for(int i=0;i<e[u].size();i++)
{
int &v=e[u][i];

if(v==prt)continue;
if(DFN[v]!=-1&&DFN[v]>=DFN[u])continue;

stk[top++]=edge(u,v);

if(DFN[v]==-1)
{
child++;
DFS(v,u);
LOW[u]=min(LOW[u],LOW[v]);

if(LOW[v]>=DFN[u])
{
iscut[u]=true;
vector<edge> ans;
while(!(stk[top-1]==edge(u,v)))
{
ans.push_back(stk[top-1]);
top--;
}
ans.push_back(stk[top-1]);
top--;
Ans.push_back(ans);
}

}
else LOW[u]=min(LOW[u],DFN[v]);
}

if(prt==-1&&child==1)iscut[u]=false;
}

void Solve()
{
for(int i=1;i<=n;i++)
if(DFN[i]==-1)DFS(i,-1);
}
}T;

int main()
{
int n;
while(scanf("%d",&n)==1)
{
T.init(n);
int m;
scanf("%d",&m);
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
T.AddEdge(u,v);
}
T.Solve();
for(int i=0;i<T.Ans.size();i++)
{
for(int j=0;j<T.Ans[i].size();j++)
printf("(%d,%d) ",T.Ans[i][j].u,T.Ans[i][j].v);
printf("\n");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: