演算法學習之路|PlayOnWords(尤拉道路+dfs)

kissjz發表於2018-02-14

題目大意:給出n個單詞,問能否把這些單詞首尾相接(每個單詞第一個字母和上一個單詞最後一個字母相同)

分析:把單詞相接轉換成26字母間的有向圖,問題就轉化成求有向圖是否構成尤拉道路。

ac程式碼:

#include
#include
#include
#include
#define maxn 30
using namespace std;
int vis[maxn],G[maxn][maxn],f[maxn],in[maxn],out[maxn];
void dfs(int x)
{
    vis[x]=true;
    for(int i=0;i<maxn;i++)//向前搜尋
    {
        if(G[i][x]&&!vis[i])
            dfs(i);
    }
    for(int i=0;i<maxn;i++)//向後搜尋
    {
        if(G[x][i]&&!vis[i])
            dfs(i);
    }
}

int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--){
        memset(G, 0, sizeof(G));
        memset(in, 0, sizeof(in));
        memset(out, 0, sizeof(out));
        memset(vis, 0, sizeof(vis));
        char str[1005];
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",str);
            G[str[0]-`a`][str[strlen(str)-1]-`a`]++;
            out[str[0]-`a`]++;//出度
            in[str[strlen(str)-1]-`a`]++;//入度
        }
        bool flag=true;
        int num1=0,num2=0;
        for(int i=0;i<maxn;i++)//判斷入度出度是否滿足條件
        {
             if(!flag) 
             break; 
            if(in[i]!=out[i])
            {
                 if(in[i]==out[i]+1)
                     num1++; 
                 else if(out[i]==in[i]+1)
                     num2++; 
                 else 
                 {
                     flag=false;
                     break; 
                 } 
            } 
        } 
        if(num1&&num2&&num1+num2>2)
            flag=false;
        if(flag)
        {
            for(int i=0;i<maxn;i++)
                if(out[i])
                {
                    dfs(i);
                    break;
                }
            bool flag2=true;
            for(int i=0;i<maxn;i++)//判斷是否連通
            {
                if(in[i]&&!vis[i])
                {
                    flag2=false;
                    break;
                }
                if(out[i]&&!vis[i])//這個if可以去掉,重複了
                {
                    flag2=false;
                    break;
                }
            }
            if(flag2) printf("Ordering is possible.
");
            else printf("The door cannot be opened.
");
        }
        else
        {
            printf("The door cannot be opened.
");
        }
    }
    return 0;
}

此處用的不是並查集而是dfs,因此會出現一個問題,如果只向前搜尋可能會導致無環圖沒有完整遍歷,比如從單詞鏈中間某一個單詞開始dfs的話,會使得這個單詞之間的單詞被忽略掉,因為是有向圖,從而即使是從一個連通分量中的點(單詞),也沒有被標記過。

順便回顧dfs,要注意邊界條件。


相關文章