tarjan
- 夫妻之间:girl→boygirl
- 旧恋人之间:boy→girlboy
然后判断每对夫妻是否在一个强联通分量里即可
#include<bits/stdc++.h>
using namespace std;
const int maxn=10005;
const int maxm=2e4+5;
int n,m,inin[maxn],head[maxn],dfn[maxn],dfs_times,low[maxn],tot;
map <string,int> s;
struct edge
{
int to,nxt;
}e[maxm<<1];
int col[maxn],col_num;
void add(int x,int y)
{
e[++tot].to=y;
e[tot].nxt=head[x];
head[x]=tot;
}
int st[maxn],top;
void tarjan(int x)
{
dfn[x]=low[x]=++dfs_times;
st[++top]=x;
inin[x]=1;
for(int i=head[x];i;i=e[i].nxt)
{
int to=e[i].to;
if(!dfn[to])
{
tarjan(to);
low[x]=min(low[x],low[to]);
}
else if(inin[to]) low[x]=min(low[x],dfn[to]);
}
if(dfn[x]==low[x])
{
++col_num;
do
{
col[st[top]]=col_num;
inin[st[top]]=0;
}while(st[top--]!=x);
}
}
int main()
{
// freopen("marriage.in","r",stdin);
// freopen("marriage.out","w",stdout);
scanf("%d",&n);
string x,y;
for(int i=1;i<=n;i++)
{
cin>>x>>y;
s[x]=i;
s[y]=i+n;
add(s[x],s[y]);
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
cin>>x>>y;
add(s[y],s[x]);
}
for(int i=1;i<=2*n;i++)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=n;i++)
{
if(col[i]==col[i+n]) printf("Unsafe\n");
else printf("Safe\n");
}
return 0;
}