1. 程式人生 > >HDU 3849(求橋)

HDU 3849(求橋)

問題描述

社交網路近來很受歡迎。網路幫助我們瞭解那些我們正在緊張關注的人,讓我們跟上現代潮流的步伐。
但是怎麼樣?
通過什麼方法我們可以知道我們想要的資訊?在某些網站,也許人人,基於社交網路,我們主要通過與那些“流行領導者”的某些關係得到資訊。似乎他們知道每一個最近的新聞並且總是線上他們總是釋出突發新聞,通過我們與他們的關係,我們被告知“幾乎所有事情”。
(啊哈,“幾乎所有東西”,這是一個衝動的社會!)
現在,是時候知道我們的問題是什麼了。我們想知道哪些關鍵關係使我們與社交網路中的其他關係相關。
好,
這意味著如果關係被取消或不再存在,我們將永遠失去與社交網路中某些人的關係。顯然,我們不想失去與那些人的關係。我們必須知道這些關鍵關係是什麼,以便我們可以更好地保持這些關係。
我們將為您提供關係描述圖,您應該在其中找到關鍵關係。
我們都知道兩個人之間的關係是相互的,因為這個關係描述圖並沒有描述twitter或google +中的關係。例如,在這個問題的情況下,如果我認識你,你也認識我。

 輸入

輸入是關係描述圖。
在第一行中,整數t表示個案數(t <= 5)。
在第二行中,整數n表示人數(1 <= n <= 10000),整數m表示這些人之間的關係數(0 <= m <= 100000)。
從第二行到(m + 1)行,在每一行中,有兩個字串A和B(1 <= length [a],length [b] <= 15,假設只存在小寫字母)。
我們保證在關係描述圖中,沒有人與自己(自己)有關係,並且不會有相同的關係(即,如果“aaa bbb”已經存在於一行中,則在以下行中,贏得了'不再是“aaa bbb”或“bbb aaa”)。
我們不保證所有這些人都有相互關係(無論是直接還是間接),所以當然,關係描述圖可能沒有關鍵關係。

產量

在第一行中,輸出整數n,表示關係描述對映中的鍵關係數。
從第二行到第(n + 1)行,根據輸入的順序和格式輸出這些關鍵關係。

樣本輸入
1
4 4
saerdna aswmtjdsj
aswmtjdsj mabodx
mabodx biribiri
aswmtjdsj biribiri
 

樣本輸出
1
saerdna aswmtjdsj

題意:

      給你一個無向圖(可能不連通,但是無自環,無重邊),如果本圖不連通,那麼直接輸出0。否則要你輸出圖中的每條橋邊,要求按輸入邊的順序輸出。

程式碼:

#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
const int maxn=10000+10;
const int maxm=100000+10;
int n,m;
struct node
{
    char s[20];
    bool operator <(const node& rhs)const
    {
        return strcmp(s,rhs.s)<0;
    }
};
map<node,int> mp;//將字串node對映成節點編號
struct Edge
{
    node u,v;
    bool flag;//標記該邊是不是橋
}e[maxm];
vector<int> G[maxn];
int pre[maxn],low[maxn];
int dfs_clock;
void tarjan(int u,int fa)
{
    low[u]=pre[u]=++dfs_clock;
    for(int i=0;i<G[u].size();i++)
    {
        int v=G[u][i];
        if(v==fa) continue;
        if(!pre[v])
        {
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
        }
        else low[u] = min(low[u],pre[v]);
    }
}
int main()
{
    int T; scanf("%d",&T);
    while(T--)
    {
        int id=0;
        scanf("%d%d",&n,&m);
        mp.clear();
        dfs_clock=0;
        memset(pre,0,sizeof(pre));
        for(int i=1;i<=n;i++) G[i].clear();
        for(int i=0;i<m;i++)
        {
            e[i].flag=false;
            scanf("%s%s",e[i].u.s,e[i].v.s);
            if(mp.find(e[i].u)==mp.end()) mp[e[i].u]= ++id;
            if(mp.find(e[i].v)==mp.end()) mp[e[i].v]= ++id;
            int x = mp[e[i].u], y=mp[e[i].v];
            G[x].push_back(y);
            G[y].push_back(x);
        }
        tarjan(1,-1);
        bool ok=true;//判斷是否連通圖
   /*
判斷是否還有節點的pre值==0。
如果存在這種點,那麼該圖不連通.

   */
        for(int i=1;i<=n;i++)if(!pre[i])
        {
            ok=false;
            break;
        }
        if(!ok) printf("0\n");
        else
        {
            int ans=0;//計數橋總數
            for(int i=0;i<m;i++)
            {
                int u=mp[e[i].u], v=mp[e[i].v];
                if(low[u]>pre[v]||low[v]>pre[u]) e[i].flag=true,ans++;
            }
            printf("%d\n",ans);
            for(int i=0;i<m;i++)if(e[i].flag)
                printf("%s %s\n",e[i].u.s,e[i].v.s);
        }
    }
    return 0;
}