昨天CF没有做出D
原因竟是不会二分
令人感叹!
不过这道题很有意思啊!
每次断一次正经关系 跑一遍匈牙利 要是成功的话 也就是跑过的地方都匹配
最开始想的是连边 偶数环染色 但是感觉太复杂了 确实是没注意到n<4000 可以O(n^2)过啊!
#include <bits/stdc++.h>
using namespace std;
const int N = 2e4+10;
const int M = 1e4+10;
const int mod = 998244353;
#define int long long
#define endl '\n'
#define Endl '\n'
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
int n,m,h[N],e[N<<1],ne[N<<1],idx,match[N<<1];
bool st[N<<1];
map<string,int>a;
map<string,int>b;
void add(int a,int b){
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
int find(int x){
for(int i=h[x];~i;i=ne[i]){
int j=e[i];
if(!st[j]){
st[j]=true;
if(j==x+n)continue;
if(!match[j]||find(match[j]))return true;
}
}
return false;
}
signed main(){
fast
cin>>n;
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++){
string A,B;cin>>A>>B;
a[A]=i,b[B]=i+n;
match[i]=i+n,match[i+n]=i;
add(i,i+n);
}
cin>>m;
for(int i=1;i<=m;i++){
string A,B;cin>>A>>B;
add(a[A],b[B]);
}
for(int i=1;i<=n;i++){
match[i+n]=0;
if(find(i))cout<<"Unsafe"<<Endl;
else cout<<"Safe"<<endl;
match[i+n]=i;
memset(st,false,sizeof st);
}
return 0^0;
}