tarjan 缩点+向上标记法 0pts 求救
查看原帖
tarjan 缩点+向上标记法 0pts 求救
1285691
yinbe2楼主2024/12/28 13:44
#include<iostream>
#include<vector>
using namespace std;
const int N=2e5+5,M=5e5+5;
int n,tot,head[N],nxt[M<<1],ver[M<<1],cnt,root,Min=1<<30;
int totc,headc[N<<1],nxtc[M<<1],verc[M<<1],depth[N<<1],fa[N<<1],id[N<<1];
int dfn[N],low[N],num,s[N],len,c[N];
bool cut[N],vis[N<<1];
vector<int>vcc[N];
void dfs(int x,int d,int f)
{
	vis[x]=true;
	depth[x]=d;
	fa[x]=f;
	for(int i=headc[x];i;i=nxtc[i])
	{
		int y=verc[i];
		if(!vis[y])
			dfs(y,d+1,x);
	}
}
void add(int x,int y)
{
	tot++;
	ver[tot]=y;
	nxt[tot]=head[x];
	head[x]=tot;
}
void addc(int x,int y)
{
	totc++;
	verc[totc]=y;
	nxtc[totc]=headc[x];
	headc[x]=totc;
}
void tarjan(int x)
{
	int flag=0;
	num++;
	dfn[x]=num;
	low[x]=num;
	s[++len]=x;
	for(int i=head[x];i;i=nxt[i])
	{
		int y=ver[i];
		if(!dfn[y])
		{
			tarjan(y);
			low[x]=min(low[x],low[y]);
			if(low[y]>=dfn[x])
			{
				flag++;
				if(x!=root||flag>=2)
					cut[x]=true;
				int z;
				vcc[++cnt].push_back(x);
				do
				{
					z=s[len--];
					c[z]=cnt;
					vcc[cnt].push_back(z);
				}while(z!=y);
			}
		}
		else
			low[x]=min(low[x],dfn[y]);
	}
}
int main()
{
	scanf("%d",&n);
	while(1)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		if(u==0&&v==0)
			break;
		add(u,v);
		add(v,u);
	}
	tarjan(1);
	num=cnt;
	for(int i=1;i<=n;i++)
	{
		if(cut[i])
		{
			c[i]=++num;
			id[num]=i;
		}	
	}
	for(int i=1;i<=cnt;i++)
	{
		for(int x:vcc[i])
		{
			if(cut[x])
			{
				addc(i,c[x]);
				addc(c[x],i);
			}
		}
	}
	int x,y;
	scanf("%d%d",&x,&y);
		dfs(c[1],0,0);
		x=c[x];
		y=c[y];
		if(depth[x]<depth[y])
			swap(x,y);
		while(depth[x]!=depth[y])
		{
			x=fa[x];
			if(x>cnt)
				Min=min(Min,id[x]);
		}
		while(x!=y)
		{
			x=fa[x];
			y=fa[y];
			if(x>cnt)
				Min=min(Min,id[x]);
			if(y>cnt)
				Min=min(Min,id[y]);							
		}
		if(Min==(1<<30))
			printf("No solution");
		else
			printf("%d",Min);
}
2024/12/28 13:44
加载中...