hdu1116Play on Words

第一次接触欧拉路,看了大神的解题报告后写出
 
并查集+欧拉回路,先要用并查集判断是否连通,然后再根据每个节点的入度与出度判断是否为欧拉回路或欧拉路
如果所有点入度等于出度,则为欧拉回路
如果起点的入度比出度小一且终点的入度比出度大一,则为欧拉路
 
#include <iostream>
#include <cstring>
using namespace std;

#ifndef ONLINE_JUDGE
#include <fstream>
ifstream fin("test.txt");
#define cin fin
#endif
int p[27],vis[27],in[27],out[27];
int find(int r)    //刚开始竟然把这里返回值设为bool,脑残了,找了半天找不到错
{
    return r == p[r] ? r : p[r] = find(p[r]);
}
void ini()
{
    int i;
    for(i = 0; i < 26; ++i)
    p[i] = i;
    memset(in,0,sizeof(in));
    memset(out,0,sizeof(out));
    memset(vis,0,sizeof(vis));
}
int main()
{
    ios::sync_with_stdio(false);
    int t,n;
    string str;
    cin >> t;
    while(t--)
    {
        ini();
        cin >> n;
        while(n--)
        {
            cin >> str;
            int l = str.length();
            int a = str[0] - 'a',b = str[l-1] - 'a';
            out[a]++;
            in[b]++;
            vis[a] = vis[b] = 1;
            int x = find(a);
            int y = find(b);
            if(x != y)
            p[y] = x;
        }
        int cnt = 0;
        for(int i = 0; i < 26; ++i)
        if(vis[i] && p[i] == i)
        cnt++;
        if(cnt > 1)
        {
            cout << "The door cannot be opened." << endl;
            continue;
        }
        int i,j = 0;
        for(i = 0; i < 26; ++i)
        if(in[i] != out[i] && vis[i])
        str[j++] = i;
        if(!j)
        {
            cout << "Ordering is possible." << endl;
        }
        else
        {
            if(j == 2 && (in[str[0]] - out[str[0]] == 1 && out[str[1]] - in[str[1]] == 1
            || in[str[1]] - out[str[1]] == 1 && out[str[0]] - in[str[0]] == 1))
            cout << "Ordering is possible." << endl;
            else
            cout << "The door cannot be opened." << endl;
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/fchx/p/3097581.html