LUOGU P1407 [国家集训队]稳定婚姻
解题思路
让所有夫妇之间连男到女的边,所有情人之间连女到男的边,然后用$tarjan$,如果对于一对夫妻在强连通分量里,那么就是不稳定的,因为他们可以绕一圈。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> using namespace std; const int MAXN = 8005; const int MAXM = 40005; int n,m,cnt,head[MAXN],tot,to[MAXM],nxt[MAXM]; int dfn[MAXN],low[MAXN],num,stk[MAXN],top,col[MAXN],col_num; bool vis[MAXN]; string s1,s2; map<string,int> mp; inline void add(int bg,int ed){ to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt; } void tarjan(int x){ dfn[x]=low[x]=++num;vis[x]=1;stk[++top]=x; for(register int i=head[x];i;i=nxt[i]){ int u=to[i]; if(!dfn[u]) {tarjan(u);low[x]=min(low[x],low[u]);} else if(vis[u]) low[x]=min(dfn[u],low[x]); } if(dfn[x]!=low[x]) return; col[x]=++col_num;vis[x]=0; while(stk[top]!=x){ vis[stk[top]]=0; col[stk[top--]]=col_num; }top--; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ cin>>s1>>s2;add(tot+1,tot+2); mp[s1]=++tot;mp[s2]=++tot; } scanf("%d",&m); for(int i=1;i<=m;i++) cin>>s1>>s2,add(mp[s2],mp[s1]); for(int i=1;i<=2*n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++) puts(col[i<<1]==col[(i<<1)-1]?"Unsafe":"Safe"); return 0; }