如果把婚♂外♂情看做有向边,可以发现Safe就是婚姻关系出现了环,那么tarjan一下看看所属强连通分量大小是否为1就好了。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=32005;
int head[N],next[N],list[N],dfn[N],low[N],q[N],num[N],ret[N],belong[N];
bool inset[N];
int n,m,cnt,top,tot,scc,yzy;
int ch[N][52];
char s[10];
inline void insert(int x,int y)
{
next[++cnt]=head[x];
head[x]=cnt;
list[cnt]=y;
}
inline int get(char c)
{
if (c>='a'&&c<='z') return c-'a';
return c-'A'+26;
}
inline int add()
{
int len=strlen(s),c,now=0;
for (int i=0;i<len;i++)
{
c=get(s[i]);
if (ch[now][c]) now=ch[now][c];
else now=ch[now][c]=++yzy;
}
return now;
}
void dfs(int x)
{
dfn[x]=low[x]=++tot;
inset[x]=true;
q[++top]=x;
for (int i=head[x];i;i=next[i])
if (!dfn[list[i]])
{
dfs(list[i]);
low[x]=min(low[x],low[list[i]]);
}
else if (inset[list[i]]) low[x]=min(low[x],dfn[list[i]]);
if (dfn[x]==low[x])
{
int i=-1; scc++;
while (i!=x)
{
i=q[top--];
inset[i]=false;
num[scc]++;
ret[i]=scc;
}
}
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%s",s);
belong[add()]=i;
scanf("%s",s);
belong[add()]=i;
}
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
scanf("%s",s);
int u=belong[add()];
scanf("%s",s);
int v=belong[add()];
insert(u,v);
}
for (int i=1;i<=n;i++)
if (!dfn[i]) dfs(i);
for (int i=1;i<=n;i++)
if (num[ret[i]]>1) puts("Unsafe"); else puts("Safe");
return 0;
}