一开始看到题目以为是二分图匹配直接上
但是显然是会T的呀
一条边一条边删过去然后跑二分图匹配,再加上2s的时限
一看就很玄学
然后你画图你会发现
如果一对夫妻在同一个强连通分量时,显然是Unsafe的
画图很明显,就是类似于每一个原配都可以被环上的下一个点所替代,然后形成的环上的每一个点都可以被下一个点替代
然后不再环上的点直接和原配就可以了
然后就直接tarjan就可以了
get了一个新技能,判断某一二分图是否能完全匹配时可以不用暴力匈牙利,可以用tarjan
然后下面是代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<map>
using namespace std;
int n,m,col,tot,cnt,x[2003],y[2003];
stack<int> s;
map<string,int> name;
int color[100003],low[100003],dfn[100003];
int inst[100003];
int to[100003],nex[100003],head[100003];
void add(int u,int v){
to[++tot]=v;
nex[tot]=head[u];
head[u]=tot;
}
void tarjan(int node){
dfn[node]=++cnt;
low[node]=cnt;
s.push(node);
inst[node]=1;
for(int i=head[node];i;i=nex[i]){
int t=to[i];
if(!dfn[t]){
tarjan(t);
low[node]=min(low[node],low[t]);
}
if(inst[t]==1){
low[node]=min(low[node],dfn[t]);
}
}
if(low[node]==dfn[node]){
col++;
while(s.top()!=node){
color[s.top()]=col;inst[s.top()]=2;
s.pop();
}
color[node]=col;inst[node]=2;
s.pop();
}
}
void doit(){
cnt=col=0;
memset(inst,0,sizeof(inst));
for(int i=1;i<=2*n;i++){
if(!inst[i]){
tarjan(i);
}
}
for(int i=1;i<=n;i++){
if(color[i]==color[i+n]){
cout<<"Unsafe"<<endl;
}else{
cout<<"Safe"<<endl;
}
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
string wife,husband;
cin>>wife>>husband;
name[wife]=i;
name[husband]=i+n;
add(i,n+i);
}
cin>>m;
for(int i=1;i<=m;i++){
string gf,bf;
cin>>gf>>bf;
add(name[bf],name[gf]);
}
doit();
return 0;
}
/*
in1:
2
Melanie Ashley
Scarlett Charles
1
Scarlett Ashley
out1:
Safe
Safe
in2:
2
Melanie Ashley
Scarlett Charles
2
Scarlett Ashley
Melanie Charles
out2:
Unsafe
Unsafe
*/