luogu P1407 穩定婚姻-tarjan縮點
題目背景
原《工資》重題請做2397
題目描述
我國的離婚率連續7年上升,今年的頭兩季,平均每天有近5000對夫婦離婚,大城市的離婚率上升最快,有研究婚姻問題的專家認為,是與簡化離婚手續有關。
25歲的姍姍和男友談戀愛半年就結婚,結婚不到兩個月就離婚,是典型的“閃婚閃離”例子,而離婚的導火線是兩個人爭玩電腦遊戲,丈夫一氣之下,把電腦炸爛。
有社會工作者就表示,80後求助個案越來越多,有些是與父母過多幹預有關。而根據民政部的統計,中國離婚五大城市首位是北京,其次是上海、深圳,廣州和廈門,那麽到底是什麽原因導致我國成為離婚大國呢?有專家分析說,中國經濟急速發展,加上女性越來越來越獨立,另外,近年來簡化離婚手續是其中一大原因。
——以上內容摘自第一視頻門戶
現代生活給人們施加的壓力越來越大,離婚率的不斷升高已成為現代社會的一大問題。而其中有許許多多的個案是由婚姻中的“不安定因素”引起的。妻子與丈夫吵架後,心如絞痛,於是尋求前男友的安慰,進而夫妻矛盾激化,最終以離婚收場,類似上述的案例數不勝數。
我們已知n對夫妻的婚姻狀況,稱第i對夫妻的男方為Bi,女方為Gi。若某男Bi與某女Gj曾經交往過(無論是大學,高中,亦或是幼兒園階段,i≠j),則當某方與其配偶(即Bi與Gi或Bj與Gj)感情出現問題時,他們有私奔的可能性。不妨設Bi和其配偶Gi感情不和,於是Bi和Gj舊情復燃,進而Bj因被戴綠帽而感到不爽,聯系上了他的初戀情人Gk……一串串的離婚事件像多米諾骨牌一般接踵而至。若在Bi和Gi離婚的前提下,這2n個人最終依然能夠結合成n對情侶,那麽我們稱婚姻i為不安全的,否則婚姻i就是安全的。
給定所需信息,你的任務是判斷每對婚姻是否安全。
輸入輸出格式
輸入格式:
第一行為一個正整數n,表示夫妻的對數;
以下n行,每行包含兩個字符串,表示這n對夫妻的姓名(先女後男),由一個空格隔開;
第n+2行包含一個正整數m,表示曾經相互喜歡過的情侶對數;
以下m行,每行包含兩個字符串,表示這m對相互喜歡過的情侶姓名(先女後男),由一個空格隔開。
輸出格式:
輸出文件共包含n行,第i行為“Safe”(如果婚姻i是安全的)或“Unsafe”(如果婚姻i是不安全的)。
輸入輸出樣例
輸入樣例#1:2
Melanie Ashley
Scarlett Charles
1
Scarlett Ashley
輸出樣例#1: Safe
Safe
輸入樣例#2: 2
Melanie Ashley
Scarlett Charles
2
Scarlett Ashley
Melanie Charles
輸出樣例#2: Unsafe
Unsafe
說明
對於20%的數據,n≤20;
對於40%的數據,n≤100,m≤400;
對於100%的數據,所有姓名字符串中只包含英文大小寫字母,大小寫敏感,長度不大於8,保證每對關系只在輸入文件中出現一次,輸入文件的最後m行不會出現未在之前出現過的姓名,這2n個人的姓名各不相同,1≤n≤4000,0≤m≤20000。
像我這樣優秀的男人,又怎麽會因穩定婚姻這點小事兒發愁呢。
思路解析:
看起來並不是太難。
題目中人名是字符串,我們當然不能用字符串了,我們以人名出現的順序來編號。
我們用一個map型的 f數組表示f[ ][ ],表示人名的編號是幾,例如:f[“dad”][8], 叫dad的編號是8.
然後就是建邊了,在這個男性主宰的世界裏,當然要女性向男性建邊了(嗯?我說啥了麽,我想沒有吧),單向邊。
接下來的要重點註意了啊
輸入的m行時,需要男性向女性建邊,因為在上邊時並且你需要讓這牽連到的人連成環,所以我們是女性向男性建邊的(仔細想想)。
搞明白上邊就好辦了,所點以後,判斷每一個強聯通分量中有幾個點,要是有1個以上的點則表明婚姻有危險(單向邊,夫妻之間若沒有危險是不會在一個強聯通分量中的)
每位夫妻判斷一下其所在的環,輸出就好啦(註意大小寫,我在這掛掉了)
AC代碼:
/*.................... 作者:Manjusaka 時間:2018/7/10 題目:P1407 [國家集訓隊]穩定婚姻 ......................*/ #include <iostream> #include <cstdio> #include <map> #define N int(8e3+2) #define M int(4e4+2) using namespace std; string f[N]; map <string,int> v; string a,b; int n,m,sum; struct ahah{ int nxt,to; }edge[M]; int head[N],tot; void add(int x,int y) { edge[++tot].nxt=head[x],edge[tot].to=y,head[x]=tot; } int dfn[N],low[N],index; int stark[N],top; bool in[N]; int belong[N]; int cnt; void tarjan(int u) { dfn[u]=low[u]=++index; in[u]=1;stark[++top]=u; for(int i=head[u];i;i=edge[i].nxt) { int v=edge[i].to; if(!dfn[v]) { tarjan(v); if(low[v]<low[u])low[u]=low[v]; } else if(in[v]&&low[u]>dfn[v])low[u]=dfn[v]; } if(dfn[u]==low[u]) { int p; cnt++; do { p=stark[top--]; in[p]=0; belong[p]=cnt; }while(u!=p); } } int vis[N]; void chack() { for(int i=1;i<=sum;i++)if(!dfn[i])tarjan(i); for(int i=1;i<=sum;i++)vis[belong[i]]++; for(int i=1;i<=n*2;i+=2) { if(vis[belong[v[f[i]]]]>1)printf("Unsafe\n"); else printf("Safe\n"); } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { cin>>a>>b; f[++sum]=a,v[a]=sum; f[++sum]=b,v[b]=sum; add(sum-1,sum); } scanf("%d",&m); for(int i=1;i<=m;i++) { cin>>a>>b; add(v[b],v[a]); } chack(); }
luogu P1407 穩定婚姻-tarjan縮點