P1407 [國家集訓隊]穩定婚姻
阿新 • • 發佈:2018-12-20
最喜歡這樣的題了(最近越來越發現自己對圖論的熱愛)~
也可能是因為這種題好寫。。。
但是對自己沒有一次AC表示不舒服。
原因是陣列開小了(emmm……)……
言歸正傳:
首先是圖的存法,由於要夠成環,所以夫妻之間的邊和情侶之間的邊方向一定是相反的(因為對於無向圖的寫法我沒太大把握),至於具體方向無所謂,只要相反,就行。
然後我們的可愛的Tarjan一遍遍地跑呀跑……
看一遍,如果情侶在一個強連通分量裡,自然就是不安全的,反之安全。
有一個小技巧:
一開始我是列舉邊並且判斷是否為情侶,還要開陣列記下來誰是誰的情侶,判斷很麻煩。
切掉之後我看了一眼題解,發現意外收穫:就是我們可以規定一對情侶之間的序號相差n(這樣肯定沒有重疊嘛),這樣判斷的時候,判斷 i 和 i + n 即可。
好了直接上程式碼:
#include<cstdio> #include<iostream> #include<map> using namespace std; #define maxn 500005 int low[50000],dfn[50000],head[50000],co[50000],to[maxn],nxt[maxn],st[maxn]; int cnt,n,m,col,num,top; map<string,int> q; void add(int a,int b) { to[++cnt]=b; nxt[cnt]=head[a]; head[a]=cnt; } void Tarjan(int u) { dfn[u]=low[u]=++num; st[++top]=u; for(int i=head[u];i;i=nxt[i]) { int v=to[i]; if(!dfn[v]) { Tarjan(v); low[u]=min(low[u],low[v]); } else if(!co[v]) low[u]=min(dfn[v],low[u]); }if(low[u]==dfn[u]) { co[u]=++col; while(st[top]!=u) { co[st[top]]=col; top--; } top--; } } int main() { scanf("%d",&n); string gir,boy; for(int i=1;i<=n;i++) { cin>>gir>>boy; q[gir]=i; q[boy]=i+n; add(i,i+n); } scanf("%d",&m); for(int i=1;i<=m;i++) { cin>>gir>>boy; add(q[boy],q[gir]); } for(int i=1;i<=2*n;i++) if(!dfn[i]) Tarjan(i); for(int i=1;i<=n;i++) if(co[i]==co[i+n]) printf("Unsafe\n"); else printf("Safe\n"); return 0; }