1. 程式人生 > >UVA10129 - Play on Words

UVA10129 - Play on Words

題目:

Some of the secret doors contain a very interesting word puzzle. The team of archaeologists has to solve it to open that doors. Because there is no other way to open the doors, the puzzle is very important for us.

There is a large number of magnetic plates on every door. Every plate has one word written on it. The plates must be arranged into a sequence in such a way that every word begins with the same letter as the previous word ends. For example, the word ``acm'' can be followed by the word ``motorola''. Your task is to write a computer program that will read the list of words and determine whether it is possible to arrange all of the plates in a sequence (according to the given rule) and consequently to open the door.

題意:給你n個單詞,是否可以將所有的單詞排成一個序列,使每個單詞第一個字母與上一個單詞最後一個字母相同,輸入中有重複的單詞。

把每個單詞當作一條邊,字母看作點,題目變成判斷有向圖上是否存在一條歐拉回路。

有向圖滿足歐拉回路的條件是:除了起點和終點外, 其他點的“進出” 次數應該相等。 換句話說,除了起點和終點外, 其他點的度數應該是偶數。

對於有向圖, 則必須其中一個點的出度恰好比入度大1, 另一個的入度比出度大。

尤拉的一些名詞意思:1)尤拉路:通過圖中所有邊的簡單路。2)歐拉回路:閉合的尤拉路。3)尤拉圖:包含歐拉回路的圖。

#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define maxn 110
#define qx std::ios::sync_with_stdio(false)
#define N 2100
using namespace std;
string s;
int vis[200],n,t,in[200],out[200],f[30];
int F(int x) {return f[x]==x? x:f[x]=F(f[x]);}
void Merge(int a,int b) {a=F(a);b=F(b);if(a!=b) f[a]=b;}
int main(){
    cin>>t;
    while(t--){
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        memset(vis,0,sizeof(vis));
        for(int i=0;i<=26;i++) f[i]=i;
        cin>>n;
        for(int i=0;i<n;i++){
            cin>>s;
            int a=s[0]-'a',b=s[s.length()-1]-'a';
            out[a]++;in[b]++;
            vis[a]=1;vis[b]=1;
            Merge(a,b);
        }
        int cnt=0;
        for(int i=0;i<=26;i++)
            if(vis[i]&&F(i)==i) cnt++;//有幾個連通塊
        if(cnt>1){//多於一個則不能組成一條
            printf("The door cannot be opened.\n");
            continue;
        }
        cnt=0;
        int t1=-1,t2=-1;
        bool ok=true;
        for(int i=0;i<=26;i++)
            if(vis[i]&&in[i]!=out[i])//入度!=出度
                if(in[i]+1==out[i]&&t1==-1) t1=i;//入度比出度大一
                else if(in[i]==out[i]+1&&t2==-1) t2=i;//出度比入度大一
                else ok=false;
        printf("%s\n",ok ? "Ordering is possible.":"The door cannot be opened.");
    }
    return 0;
}