https://www.luogu.com.cn/problem/P1407
这里最主要是建边有难点,其他就是一个Tarjan板子,刚开始我想的是夫妻之间建男
⟶
\longrightarrow
⟶女的单边,前情侣之间建双向边,然后就一直wawawa,然后反过来就行了,
夫妻之间建双向边,此时就是一个强连通分量,可以缩成一个点,然后前情侣之间建单边,如果构成强连通,就说明Unsafe,否则Safe.
#include <iostream>
#include <cstring>
#include <cmath>
#include <bitset>
#include <queue>
#include <vector>
#include <cstdio>
#include <set>
#include <stack>
#include <assert.h>
#include <sstream>
#include <cstring>
#include <algorithm>
#include <map>
#define rep(i, a, b) for (long long i= a; i <= b; i++)
#define reps(i, a, b) for (long long i = a; i >= b; i--)
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) a*b/gcd(a,b)
#define ls(node) tree[node].ls
#define rs(node) tree[node].rs
#define l(node) tree[node].l
#define r(node) tree[node].r
#define val(node) tree[node].val
#define sum(node) tree[node].sum
#define lazy(node) tree[node].lazy
#define lazy1(node) tree[node].lazy1
#define lazy2(node) tree[node].lazy2
#define tr(node) tree[node]
//#pragma GCC optimize(2)
using namespace std;
const int N=1e6+7;
const int M=3e4+7;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
typedef long long ll;
#define Rep(i,a,b)for(ll i=a;i<=b;i++)
inline ll read()
{
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
vector<int>G[N];
int dfn[N],low[N],vis[N],Stack[N],point[N],val[N],out[N],in[N];
int top=0,times=0,sum=0,n,m;
void tarjan(int x)
{
dfn[x]=++times;
low[x]=times;
vis[x]=1;
Stack[++top]=x;
for(int i=0;i<G[x].size();i++){
int v=G[x][i];
if(!dfn[v]){
tarjan(v);
low[x]=min(low[x],low[v]);
}else if(vis[v]){
low[x]=min(low[x],low[v]);
}
}
if(dfn[x]==low[x]){
point[x]=++sum;
val[sum]++;
vis[x]=0;
while (Stack[top]!=x){
point[Stack[top]]=sum;
vis[Stack[top--]]=0;
val[sum]++;
}
top--;
}
}
struct edge
{
int x,y;
}e[N];
vector<int>E[N];
map<string,int>mp;
int main()
{
n=read();
int cnt=0;
rep(i,1,n){
string a,b;
cin>>a>>b;
mp[a]=i,mp[b]=i;
//G[mp[a]].push_back(mp[b]);
}
m=read();
rep(i,1,m){
string a,b;
cin>>a>>b;
// G[mp[b]].push_back(mp[a]);
G[mp[a]].push_back(mp[b]);
}
rep(i,1,n)if(!dfn[i])tarjan(i);
rep(i,1,n){
if(val[point[i]]!=1)puts("Unsafe");
else puts("Safe");
}
}