这道题目建图还是很奇妙的。
把一对夫妻抽象为一个点i。那么如果夫妻对i的男方和夫妻对j的女方有关♂(jian)♀系♂(qing),那么就连一条边i->j,那么如果存在一个环就说明不(hui)安(chu)全(gui)。
Tarjan强连通分量跑跑就好了。
AC代码如下:
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#define N 40005
using namespace std;
int n,m,cnt,tot,dfsclk,fst[N],pnt[N],nxt[N],pos[N],low[N],stk[N],tp,scc[N],sum[N];
struct stg{
char ch[10];
void read(){ scanf("%s",ch); }
}s;
bool operator <(stg a,stg b){
int len1=strlen(a.ch),len2=strlen(b.ch),i;
for (i=0; i<len1 && i<len2; i++){
if (a.ch[i]<b.ch[i]) return 1; if (a.ch[i]>b.ch[i]) return 0;
}
return len1<len2;
}
map<stg,int> mp1,mp2;
void add(int x,int y){
pnt[++tot]=y; nxt[tot]=fst[x]; fst[x]=tot;
}
void dfs(int x){
pos[x]=low[x]=++dfsclk; stk[++tp]=x; int p;
for (p=fst[x]; p; p=nxt[p]){
int y=pnt[p];
if (!pos[y]){
dfs(y); low[x]=min(low[x],low[y]);
} else if (!scc[y]) low[x]=min(low[x],pos[y]);
}
if (low[x]==pos[x])
for (cnt++; ; ){
scc[stk[tp]]=cnt; sum[cnt]++;
if (stk[tp--]==x) break;
}
}
int main(){
scanf("%d",&n); int i,x,y;
for (i=1; i<=n; i++){
s.read(); mp1[s]=i;
s.read(); mp2[s]=i;
}
scanf("%d",&m);
while (m--){
s.read(); x=mp1[s];
s.read(); y=mp2[s]; add(x,y);
}
for (i=1; i<=n; i++){
if (!pos[i]) dfs(i);
puts((sum[scc[i]]>1)?"Unsafe":"Safe");
}
return 0;
}
by lych
2016.3.26