1. 程式人生 > >luogu P1407 穩定婚姻-tarjan縮點

luogu P1407 穩定婚姻-tarjan縮點

das edge 長度 ring bool 過多 正整數 tex ...

題目背景

原《工資》重題請做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縮點