1. 程式人生 > >UVA10129-歐拉回路-DFS

UVA10129-歐拉回路-DFS

第一次寫部落格,以前一直沒有總結過,現在開始對自己學的東西做一些記錄吧,方便以後複習或者就當作留個腳印。

筆者目前大一,水平弱弱弱…有不正確的地方或者可以改進的地方還望指出。

找夥伴,有想一起學習的朋友可以一起交流交流。email:   [email protected]

題目大意:輸入n個單詞,判斷是否能把所有單詞連線成一個串,使得每個單詞首字母與前一個單詞尾字母相同。

思路:

1:把每個單詞看作一座橋,二十六給英文字母看作節點,儲存有向圖。

2:判斷整個有向圖的奇點數是否大於2,大於2則不存在尤拉道路,存在則走第三步。

3:判斷圖的連通性,筆者目前只會用DFS(並查集還沒學),

此時可以看作無向圖(稍微提高效率)。若連通則存在尤拉道路。

注意:

思路講起來簡潔,然而每次實現都會遇到各種問題。(筆者太弱了)

若奇點數為2,判斷連通性的時候一定要是注意起點是出度大於入度的那個節點。

若奇點數為0,(容易忽略)一定要找一個存在橋的節點。

程式碼:

話不多說,直接上AC程式碼。看了下各路大神的程式碼,都這麼短!!!都不好意思貼上來了。

不太想寫註釋了,程式碼如下。

#include<iostream>
#include<string>
#include<cstring>
#include<cstdlib>
using namespace std;

bool G[26][26];
int out_cnt[26],in_cnt[26];

void dfs(int in)
{
    for(int i=0;i<26;++i)
    {
        if(G[in][i])
        {
            G[in][i]=G[i][in]=false;
            dfs(i);
        }
    }
}
bool is_cncted(int in)
{
    dfs(in);
    for(int i=0;i<26;++i)
        for(int j=0;j<26;++j)
            if(G[i][j])
                return false;
    return true;
}
int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        memset(G,0,sizeof(G));
        memset(out_cnt,0,sizeof(out_cnt));
        memset(in_cnt,0,sizeof(in_cnt));

        int t;
        cin>>t;
        string s;

        while(t--)
        {
            cin>>s;
            G[*s.begin()-'a'][*(s.end()-1)-'a']=1;
            out_cnt[*s.begin()-'a']++;
            in_cnt[*(s.end()-1)-'a']++;
        }

        int sp_in=0,sp_cnt=0,flag=1;

        for(int i=0;i<26;++i)
        {
            if(in_cnt[i]!=out_cnt[i])
            {
                if(++sp_cnt>2||abs(in_cnt[i]-out_cnt[i])!=1)
                {
                    flag=0;
                    break;
                }
                if(sp_cnt==1)
                    sp_in=i;
                else
                {
                    if(in_cnt[sp_in]-out_cnt[sp_in]+in_cnt[i]-out_cnt[i])
                    {
                        flag=0;
                        break;
                    }
                    if(out_cnt[sp_in]<in_cnt[sp_in])
                    {
                        sp_in=i;
                    }
                }
            }
        }
        if(flag)
        {
            if(!out_cnt[sp_in])
                for(int i=0;i<26;++i)
                    if(out_cnt[i])
                    {
                        sp_in=i;
                        break;
                    }
            if(!is_cncted(sp_in))
                flag=0;
        }
        if(flag)
            cout<<"Ordering is possible."<<endl;
        else
            cout<<"The door cannot be opened."<<endl;
    }
    return 0;
}