#1184 : 连通性二·边的双连通分量

贴板子。求割边。将>改为>=即可判断u是否为割点。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=20008;
const int maxm=100008;
struct fuck{
	int u,v,next;
	bool ban;
}edge[maxm<<1];
int tol;
int head[maxn];
void init()
{
	tol=0;
	memset(head,-1,sizeof(head));
}
void addedge(int u,int v)
{
	edge[tol].u=u;
	edge[tol].v=v;
	edge[tol].next=head[u];
	edge[tol].ban=false;
	head[u]=tol++;
}
int tim=0;
int pre[maxn],low[maxn];
int tarj(int u,int fa)
{
	int lowu=pre[u]=++tim;
	int child=0;
	int i,v,lowv;
	for(i=head[u];i!=-1;i=edge[i].next)
	{
		v=edge[i].v;
		if(!pre[v])
		{
			child++;
			lowv=tarj(v,u);
			lowu=min(lowu,lowv);
			if(lowv>pre[u])
			{
				edge[i].ban=true;
				edge[i^1].ban=true;
			}
		}
		else	if(pre[v]<pre[u]&&v!=fa)
			lowu=min(lowu,pre[v]);
	}
	low[u]=lowu;
	return lowu;
}
int uni[maxn];
bool vis[maxn];
void dfs(int u,int idx)
{
	int i,v;
	vis[u]=true;
	uni[u]=idx;
	for(i=head[u];i!=-1;i=edge[i].next)
	{
		if(edge[i].ban||vis[edge[i].v])	continue;
		v=edge[i].v;
		dfs(v,idx);
	}
}
int main()
{
	int i,j,n,m,u,v;
	while(scanf("%d%d",&n,&m)==2)
	{
		init();
		for(i=1;i<=m;i++)
		{
			scanf("%d%d",&u,&v);
			addedge(u,v);
			addedge(v,u);
		}
		tim=0;
		memset(pre,0,sizeof(pre));
		tarj(1,-1);
		memset(vis,false,sizeof(vis));
		int ans=0;
		for(i=1;i<=n;i++)
			if(!vis[i])
			{
				dfs(i,i);
				ans++;
			}
		printf("%d
",ans);
		for(i=1;i<=n;i++)
		{
			if(i!=1)	printf(" ");
			printf("%d",uni[i]);
		}
		printf("
");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/bitch1319453/p/4817817.html