P1407-[国家集训队]稳定婚姻【tarjan,强连通分量】

版权声明:原创,未经作者允许禁止转载 https://blog.csdn.net/Mr_wuyongcong/article/details/88751951

正题

题目链接:https://www.luogu.org/problemnew/show/P1407


题目大意

若干对夫妻,和若干对绿色关系,求每对夫妻离婚后,绿色关系是否可以重新让每个人两两配对。


解题思路

我们可以让
夫妻女的连男的
交往男的连女的

然后跑 t a r j a n tarjan ,若一对夫妻在同一个联通分量里,那么一点有办法使得男的可以到女的,而这条路径一定是偶数个点,只要让这条路径两两配对就可以重新构成关系。


c o d e code

#include<cstdio>
#include<string>
#include<algorithm>
#include<iostream>
#include<map>
#include<stack>
using namespace std;
const int N=9000,M=70000;
struct edge{
	int to,next;
}a[M];
map<string,int> num;
stack<int> s;
int tot,h,l[N],dfn[N],n,lt,inlt[N];
int low[N],ls[N],cnt;
bool v[N];
void addl(int x,int y)
{
	a[++tot].to=y;
	a[tot].next=ls[x];
	ls[x]=tot;
}
void tarjan(int x)
{
	dfn[x]=low[x]=++cnt;
	s.push(x);v[x]=1;
	for(int i=ls[x];i;i=a[i].next)
	{
		int y=a[i].to;
		if(!dfn[y]){
			tarjan(y);
			low[x]=min(low[x],low[y]);
		}
		else if(v[y])
		  low[x]=min(low[x],dfn[y]);
	}
	if(low[x]==dfn[x]){
		++lt;s.push(1);
		do{
			s.pop();
			inlt[s.top()]=lt;
			v[s.top()]=0;
		}while(s.top()!=x);
		s.pop();
	}
}
int main()
{
	tot=1;
	scanf("%d",&h);
	for(int i=1;i<=h;i++)
	{
		string a,b;
		cin>>a>>b;
		num[a]=++n;
		num[b]=++n;
		addl(n-1,n);
	}
	scanf("%d",&h);
	for(int i=1;i<=h;i++)
	{
		string a,b;
		cin>>a>>b;
		addl(num[b],num[a]);
	}
	for(int i=1;i<=n;i++)
	  if(!dfn[i]) tarjan(i);
	for(int i=1;i<=n;i+=2)
	  if(inlt[i]!=inlt[i+1]) printf("Safe\n");
	  else printf("Unsafe\n");
}

猜你喜欢

转载自blog.csdn.net/Mr_wuyongcong/article/details/88751951