Uva 10129 - Play on Words(欧拉通路)

https://vjudge.net/problem/UVA-10129

【题意】
输入n(n<=100000)个单词,是否可以把所有这些单词排成一个序列,使得每个单词的第一个字母和上一个单词的最后一个字母相同(如acm,malform,mouse)每个单词最多包含1000个字母,输入中可以有重复单词。

【思路】
紫书169页例题,把每一个单词的首字母看作起点,尾字母看作终点,做一条有向边,则该题目就是问图中有无欧拉回路或欧拉通路的问题。有向图中,首先要满足在忽略边的方向后图是联通的,通过dfs判断,其次欧拉回路存在的条件是所有顶点的出度等于入度,欧拉通路存在的条件是只有两个顶点的入度和出度不想等,且一个的入度=出度+1,另一个出度=入度+1

#include<bits/stdc++.h>
using namespace std;

const int maxl = 1050;

int n;
char s[maxl];
bool used[26];//记录一下当前的图用到了哪些结点
bool vis[26];//访问标记
int g[26][26];//邻接矩阵
int inDegree[26], outDegree[26];//入度,出度

void init() {
    memset(g, 0, sizeof(g));
    memset(vis, 0, sizeof(vis));
    memset(used, 0, sizeof(used));
    memset(inDegree, 0, sizeof(inDegree));
    memset(outDegree, 0, sizeof(outDegree));
}

void dfs(int u) {
    vis[u] = 1;
    for (int i = 0; i < 26; ++i) {
        if (!vis[i] && g[u][i]) dfs(i);
    }
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        init();
        scanf("%d", &n);
        for (int i = 0; i < n; ++i) {
            scanf("%s", s);
            int from = s[0] - 'a';
            int to = s[strlen(s) - 1] - 'a';
            used[from] = used[to] = 1;
            g[from][to] = g[to][from] = 1;//构建的是无向图,在忽略边的方向后联通即可
            ++inDegree[to];
            ++outDegree[from];
        }

        //判联通
        int cnt = 0;
        for (int i = 0; i < 26; ++i) {
            if (!vis[i] && used[i]) {
                ++cnt;
                dfs(i);
            }
        }
        if (cnt > 1) {
            printf("The door cannot be opened.\n");
            continue;
        }

        //判断入度,出度的关系
        bool ok = 1;
        int c1 = 0, c2 = 0;
        for (int i = 0; i < 26; ++i) {
            if (used[i]) {
                if (inDegree[i] == outDegree[i] + 1) ++c1;
                else if (outDegree[i] == inDegree[i] + 1) ++c2;
                else if (inDegree[i] != outDegree[i]) { ok = 0; break; }
            }
        }

        if (!ok) {
            printf("The door cannot be opened.\n");
            continue;
        }

        if ((c1 == 0 && c2 == 0) || (c1 == 1 && c2 == 1))
            printf("Ordering is possible.\n");
        else
            printf("The door cannot be opened.\n");
    }
    return 0;
}
posted @ 2018-01-30 15:48  不想吃WA的咸鱼  阅读(179)  评论(0编辑  收藏  举报