2140: 稳定婚姻
Time Limit: 2 Sec Memory Limit: 259 MBSubmit: 1321 Solved: 652
[Submit][Status][Discuss]
Description
Input
Output
输出文件共包含n行,第i行为“Safe”(如果婚姻i是安全的)或“Unsafe”(如果婚姻i是不安全的)。
Sample Input
2
Melanie Ashley
Scarlett Charles
1
Scarlett Ashley
【样例输入2】
2
Melanie Ashley
Scarlett Charles
2
Scarlett Ashley
Melanie Charles
Sample Output
Safe
Safe
【样例输出2】
Unsafe
Unsafe
HINT
Source
思路:我们把原配中男到女连边,情侣关系中女到男连边。 然后求tarjan,如果原配在一个连通块里,说明他们的婚姻不稳定。
这其实也是一个定向问题,我们把男到女表示为原配,女到男表示为婚外情,那么如果原配在一个连通块里,他们一定在一个环里,环里有偶数个边。 即这个连通块的最大匹配数=非扩展边。
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=400010; map<string,int>mp; int tot; int Laxt[maxn],Next[maxn],To[maxn],cnt,instk[maxn],q[maxn],top; int a[maxn],b[maxn],scc[maxn],scc_cnt,low[maxn],dfn[maxn],times; void add(int u,int v){ Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v;} void tarjan(int u) { low[u]=dfn[u]=++times; instk[u]=1; q[++top]=u; for(int i=Laxt[u];i;i=Next[i]){ int v=To[i]; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); } else if(instk[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]){ scc_cnt++; while(true){ int t=q[top--]; scc[t]=scc_cnt; instk[t]=0; if(u==t) break; } } } int main() { int N,M; string s,t; scanf("%d",&N); rep(i,1,N){ cin>>s>>t; if(mp.find(s)==mp.end()) mp[s]=++tot; if(mp.find(t)==mp.end()) mp[t]=++tot; a[i]=mp[s]; b[i]=mp[t]; add(a[i],b[i]); } scanf("%d",&M); rep(i,1,M){ cin>>s>>t; add(mp[t],mp[s]); } rep(i,1,tot) if(!dfn[i]) tarjan(i); rep(i,1,N) puts(scc[a[i]]==scc[b[i]]?"Unsafe":"Safe"); return 0; }