【题解】[P1407 国家集训队]稳定婚姻
很好的一道建模+图论题。
婚姻关系?很像二分图匹配呀,不过不管怎么办先建模再说。婚姻关系显然用图方面的知识解决。建图!
它给定的是字符串,所以我们使用\(map\)作匹配建点。
题意就是给你\(n\)对夫妻关系和\(m\)对情人关系,已知情人关系都可以结婚,现在假设对于某个婚姻,如果离婚,这\(2n\)个人最终依然能够结合成\(n\)对情侣,那么这样的婚姻是不稳定的。现在问每个婚姻关系的稳定性。
考虑什么样的婚姻关系是不稳定的。题目给的意思是,"这\(2n\)个人最终依然能够结合成\(n\)对情侣",我们仔细分析一下,发现如下性质:
- 依然结合成\(n\)对情侣,和这对情侣没有任何间接或直接关系的人可以忽略。\((*)\)
- 假设有两对婚姻,加入他们的男方女方分别互为情人关系,这两对婚姻都不稳定。\((**)\)
根据以上两点,我们发现,假若婚姻\(a\)的一个成员喜欢婚姻\(b\)的一个成员,那么相当于婚姻\(a\)和婚姻\(b\)连接了半条边。假若婚姻\(a\)的另一个成员也喜欢\(b\)的另一个成员那么又连了半条边。假设两个婚姻最终形成了一条边,那么他们就不稳定了!
我们考虑令情人中全是女孩子喜欢男孩子,婚姻中都是互相连边,那么假设有一个强联通分量里有偶数个人,(且不是偶数不是二),那么在这个强联通分量里的婚姻就是不稳定的。
讲不清楚QAQ直接上代码吧。
#include<bits/stdc++.h>
using namespace std;
#define RP(t,a,b) for(register int t=(a),edd=(b);t<=edd;++t)
#define DRP(t,a,b) for(register int t=(a),edd=(b);t>=edd;--t)
#define ERP(t,a) for(register int t=head[a];t;t=e[t].nx)
#define Max(a,b) ((a)<(b)?(b):(a))
#define Min(a,b) ((a)<(b)?(a):(b))
#define midd register int mid=(l+r)>>1
#define TMP template < class ccf >
TMP inline ccf qr(ccf b){
char c=getchar();
int q=1;
ccf x=0;
while(c<48||c>57)
q=c==45?-1:q,c=getchar();
while(c>=48&&c<=57)
x=x*10+c-48,c=getchar();
return q==-1?-x:x;
}
const int maxn=4004<<1;
map < string ,int > mp;
int n,m;
struct E{
int to,nx;
}e[(maxn<<1)+(20001<<1)];
int cnt;
int head[maxn];
bool in[maxn];
int dfn[maxn];
int low[maxn];
int stk[maxn];
int be[maxn];
int siz[maxn];
int timer;
int qaq;
int top;
void dfs(int now){
stk[++top]=now;
in[now]=1;
dfn[now]=low[now]=++timer;
ERP(t,now){
if(!dfn[e[t].to]){
dfs(e[t].to);
low[now]=Min(low[now],low[e[t].to]);
}
else
if(in[e[t].to])
low[now]=Min(low[now],dfn[e[t].to]);
}
if(dfn[now]==low[now]){
qaq++;
register int temp;
do{
temp=stk[top--];
in[temp]=0;
be[temp]=qaq;
++siz[qaq];
}while(top&&temp!=now);
}
}
inline void add(int fr,int to,bool f){
e[++cnt]=(E){to,head[fr]};
head[fr]=cnt;
if(f)
add(to,fr,0);
}
int mapcnt;
int main(){
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
string t1,t2;
n=qr(1);
RP(t,1,n){
cin>>t1>>t2;
mp[t1]=++mapcnt;
mp[t2]=++mapcnt;
add(mapcnt,mapcnt-1,1);
}
m=qr(1);
RP(t,1,m){
cin>>t1>>t2;
add(mp[t1],mp[t2],0);
}
RP(t,1,mapcnt)
if(!dfn[t])
dfs(t);
RP(t,1,n){
if((siz[be[t<<1]]&1)||siz[be[t<<1]]==2)
puts("Safe");
else
puts("Unsafe");
}
return 0;
}