BZOJ2140_稳定婚姻_KEY
暴力直接对于每个点跑一遍二分图匹配,能拿四十分。
然而我们考虑正解。
对于一对Couple我们建♂->♀的一条边,对于一对曾经有恋情的情侣我们建♀->♂的一条边。
跑Tarjan缩点。
判断每一对Couple,如果在同一个强连通分量里,他们就不稳定(即能通过曾经有恋情的关系跑回来)。
code:
/************************************************************** Problem: 2140 User: yekehe Language: C++ Result: Accepted Time:936 ms Memory:2232 kb ****************************************************************/ #include <cstdio> #include <map> #include <string> #include <cstring> #include <iostream> #include <algorithm> using namespace std; string S1,S2; map<string,int>MP; int N,M; struct list{ int head[8005],nxt[45000],To[45000]; int cnt; void clear(){ memset(head,-1,sizeof head); memset(nxt,-1,sizeof nxt); cnt=0; } void add(int x,int y) { To[cnt]=y; nxt[cnt]=head[x]; head[x]=cnt; cnt++; } }W; int DFN[8005],LOW[8005],stack[8005],top,nt,vis[8005],cot; int clo[8005]; void tarjan(int x) { DFN[x]=LOW[x]=++nt; stack[++top]=x; vis[x]=1; for(int i=W.head[x];i!=-1;i=W.nxt[i]){ if(!DFN[W.To[i]]){ tarjan(W.To[i]); LOW[x]=min(LOW[x],LOW[W.To[i]]); } else if(vis[W.To[i]])LOW[x]=min(LOW[x],DFN[W.To[i]]); } if(DFN[x]==LOW[x]){ cot++; while(stack[top]!=x)clo[stack[top]]=cot,vis[stack[top--]]=0; clo[stack[top]]=cot,vis[stack[top--]]=0; } } int main() { //freopen("x.txt","r",stdin); scanf("%d\n",&N); W.clear(); register int i,j; int now=0; for(i=1;i<=N;i++){ cin>>S1>>S2; if(!MP[S1])MP[S1]=++now; if(!MP[S2])MP[S2]=MP[S1]+N; W.add(MP[S1],MP[S2]); } scanf("%d\n",&M); for(i=1;i<=M;i++){ cin>>S1>>S2; W.add(MP[S2],MP[S1]); } for(i=1;i<=N*2;i++){ if(!DFN[i])tarjan(i); } for(i=1;i<=N;i++){ if(clo[i]==clo[i+N])puts("Unsafe"); else puts("Safe"); } return 0; }