正题
题目链接:https://www.luogu.org/problemnew/show/P1407
题目大意
若干对夫妻,和若干对绿色关系,求每对夫妻离婚后,绿色关系是否可以重新让每个人两两配对。
解题思路
我们可以让
夫妻女的连男的
交往男的连女的
然后跑tarjantarjantarjan,若一对夫妻在同一个联通分量里,那么一点有办法使得男的可以到女的,而这条路径一定是偶数个点,只要让这条路径两两配对就可以重新构成关系。
codecodecode
#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");
}