[bzoj2140]穩定婚姻 強連通分量

Description

我國的離婚率連續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就是安全的。給定所需

信息,你的任務是判斷每對婚姻是否安全。

Input

第一行爲一個正整數n,表示夫妻的對數;

以下n行,每行包含兩個字符串,表示這n對夫妻的姓名(先女後男),由一個空格隔開;

第n+2行包含一個正整數m,表示曾經相互喜歡過的情侶對數;

以下m行,每行包含兩個字符串,表示這m對相互喜歡過的情侶姓名(先女後男),由一個空格隔開。

所有姓名字符串中只包含英文大小寫字母,大小寫敏感,長度不大於8,

保證每對關係只在輸入文件中出現一次,輸入文件的最後m行不會出現未在之前出現過的姓名,

這2n個人的姓名各不相同,

1≤n≤4000,0≤m≤20000。

Output

輸出文件共包含n行,第i行爲“Safe”(如果婚姻i是安全的)或“Unsafe”(如果婚姻i是不安全的)。

Sample Input

【樣例輸入1】
2
Melanie Ashley
Scarlett Charles
1
Scarlett Ashley

【樣例輸入2】
2
Melanie Ashley
Scarlett Charles
2
Scarlett Ashley
Melanie Charles
 

Sample Output

【樣例輸出1】
Safe
Safe

【樣例輸出2】
Unsafe
Unsafe

 

思維難度:NOIP+

代碼難度:NOIP+

 

常數小的方法:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#include<stack>
#define ll long long
using namespace std;
const int Maxn=4005;
struct node{
	int v,next;
}e[Maxn*Maxn*2];
int man,woman,h[Maxn*2],dfn[Maxn*2],low[Maxn*2],cnt,ti,ins[Maxn*2],col[Maxn*2];
map<string,int>mp;
stack<int>Q;
void add(int u,int v){
	cnt++;
	e[cnt].v=v;
	e[cnt].next=h[u];
	h[u]=cnt;
}
inline int mn(int x,int y){
	return x<y?x:y; 
}
void dfs(int u){
	dfn[u]=low[u]=++ti;
	ins[u]=1;Q.push(u);
	for(int i=h[u];i;i=e[i].next){
		int v=e[i].v;
		if(dfn[v]==0){
			dfs(v);
			low[u]=mn(low[u],low[v]);
		}
		else{
			if(ins[v]){
				low[u]=mn(low[u],dfn[v]);
			}
		}
	}
	if(low[u]==dfn[u]){
		int i;
		do{
			i=Q.top();col[i]=u;
			Q.pop();ins[i]=0;
		}while(i!=u);
	}
}
int main(){
	freopen("a.in","r",stdin);
	int n,m;string u[Maxn],v[Maxn],s,t;
	scanf("%d\n",&n);
	for(int i=1;i<=n;i++){
		cin>>u[i]>>v[i];
		mp[u[i]]=i;mp[v[i]]=i+n;
		add(mp[v[i]],mp[u[i]]);
	}
	scanf("%d\n",&m);
	for(int i=1;i<=m;i++){
		cin>>s>>t;
		add(mp[s],mp[t]);
	}
	for(int i=1;i<=2*n;i++){
		if(!dfn[i])dfs(i);
	}
	for(int i=1;i<=n;i++){
		int fem=mp[u[i]],mal=mp[v[i]];
		if(col[fem]!=col[mal]){
			printf("Safe\n");
		}
		else{
			printf("Unsafe\n");
		}
	}
	return 0;
}

常數大的方法:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#include<stack>
#define ll long long
using namespace std;
const int Maxn=4005;
struct node{
    int v,next;
}e[Maxn*Maxn*2];
int man,woman,h[Maxn*2],dfn[Maxn*2],low[Maxn*2],cnt,ti,ins[Maxn*2],col[Maxn*2];
map<string,int>mp;
stack<int>Q;
void add(int u,int v){
    cnt++;
    e[cnt].v=v;
    e[cnt].next=h[u];
    h[u]=cnt;
}
inline int mn(int x,int y){
    return x<y?x:y; 
}
void dfs(int u){
    dfn[u]=low[u]=++ti;
    ins[u]=1;Q.push(u);
    for(int i=h[u];i;i=e[i].next){
        int v=e[i].v;
        if(!dfn[v]){
            dfs(v);
            low[u]=mn(low[u],low[v]);
        }
        else{
            if(ins[v]){
                low[u]=mn(low[u],dfn[v]);
            }
        }
    }
    if(low[u]==dfn[u]){
        int i;
        do{
            i=Q.top();col[i]=u;
            Q.pop();ins[i]=0;
        }while(i!=u);
    }
}
int main(){
    int n,m;string u[Maxn],v[Maxn],s,t;
    scanf("%d\n",&n);
    woman=n;
    for(int i=1;i<=n;i++){
        cin>>u[i]>>v[i];
        mp[u[i]]=++man;mp[v[i]]=++woman;
        add(mp[u[i]],mp[v[i]]);
        add(mp[v[i]],mp[u[i]]);
    }
    scanf("%d\n",&m);
    for(int i=1;i<=m;i++){
        cin>>s>>t;
        add(mp[s],mp[t]);
    }
    for(int i=1;i<=n*2;i++){
        if(!dfn[i])dfs(i);
    }
    for(int i=1;i<=n;i++){
        int tot=0,fg=0;int fem=mp[u[i]],mal=mp[v[i]];
        for(int j=1;j<=n*2;j++){
            if(j!=fem&&j!=mal){
                if(col[j]==col[fem]){
                    fg=1;
                    break;
                }
            }
        }
        if(fg==0){
            printf("Safe\n");
        }
        else{
            printf("Unsafe\n");
        }
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章