【二分图匹配+强连通分量】BZOJ2140 稳定婚姻
题面在这里
考虑不安全的关系,就是二分图中能重新匹配的一个子集
这个子集中所有婚姻关系都是不安全的
考虑二分图匹配的过程:每次找一条交替的增广路,使匹配数+1
那么由增广路构成的回路其实就是上文提到的子集
婚姻关系:女连向男,交往关系:男连向女
同一个强连通分量的夫妻就是不安全的
示例程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include<cstdio> #include<string> #include<map> #include<iostream> #include<algorithm> using namespace std;
const int maxn=8005,maxe=50005; int n,e,N; int tot,son[maxe],nxt[maxe],lnk[maxn]; inline void add(int x,int y){ son[++tot]=y;nxt[tot]=lnk[x];lnk[x]=tot; } map<string,int> id; int dfn[maxn],low[maxn],stk[maxn],SCC[maxn],times; bool instk[maxn]; void Tarjan(int x){ dfn[x]=low[x]=++times;instk[stk[++stk[0]]=x]=1; for (int j=lnk[x];j;j=nxt[j]) if (!dfn[son[j]]) Tarjan(son[j]),low[x]=min(low[x],low[son[j]]); else if (instk[son[j]]) low[x]=min(low[x],dfn[son[j]]); if (dfn[x]==low[x]){ SCC[0]++; while (stk[stk[0]]!=x) instk[stk[stk[0]]]=0,SCC[stk[stk[0]--]]=SCC[0]; instk[stk[stk[0]]]=0,SCC[stk[stk[0]--]]=SCC[0]; } } int main(){ scanf("%d",&n);N=0; for (int i=1;i<=n;i++){ string a,b;cin>>a>>b; id[a]=++N; id[b]=++N; add(id[b],id[a]); } scanf("%d",&e); for (int i=1;i<=e;i++){ string a,b;cin>>a>>b; add(id[a],id[b]); } for (int i=1;i<=N;i++) if (!dfn[i]) Tarjan(i); for (int i=1;i<=n;i++) if (SCC[i*2-1]==SCC[i*2]) puts("Unsafe");else puts("Safe"); return 0; }
|