例题6-16 UVA 10129 Play On Words单词

大体题意:

给你n个单词,问是否可以首尾相连,就是单词接龙!

思路:

看了下LRJ写的,用到了并查集判断有向图是否连通。

单词可以根据首字母,尾字母进行分类集合,最多26个集合!字母看作结点,单词看成有向边。

有解的情况:

1.必须连通

2.出度不等于入度的只能有0个或者2个!

有两个的情况还必须满足,一个出度比入度大1 (起点),入度比出度大1(终点)!

可以用lef表示剩余的连通图,当lef为1的时候表示可以连通!

然后把度数弄到deg数组里,入度++,出度--。

最后看是否为0.

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
const int maxn = 1000 + 10;
char str[maxn];
int is_use[26],pa[26],deg[26];
int findset(int x){return pa[x] == x ? x : pa[x] = findset(pa[x]);}
int main()
{
    int T,N;
    scanf("%d",&T);
    while(T--){
        for (int i = 0; i < 26; ++i)pa[i] = i;
        memset(deg,0,sizeof(deg));
        memset(is_use,0,sizeof(is_use));
        scanf("%d",&N);
        int lef = 26;
        for (int i = 0; i < N; ++i){
            scanf("%s",str);
            char ch1 = str[0],ch2 = str[strlen(str)-1];
            deg[ch1-'a']++;deg[ch2-'a']--;
            is_use[ch1-'a'] = is_use[ch2-'a'] = 1;
            int s1 = findset(ch1-'a'),s2 = findset(ch2-'a');
            if (s1 != s2){--lef;pa[s1] = s2;}
        }
        vector<int >d;
        for (int i = 0; i < 26; ++i){
            if (!is_use[i])--lef;
            else if (deg[i])d.push_back(deg[i]);
        }
        bool ok = false;
        if (lef == 1 && d.empty())ok=true;
        else if (d.size() == 2 && lef == 1 && ((d[0] == 1 && d[1] == -1) || (d[1] == 1 && d[0] == -1)))ok=true;
        if (!ok)printf("The door cannot be opened.\n");
        else printf("Ordering is possible.\n");
    }
    return 0;
}


你可能感兴趣的:(C语言,uva)