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