poj 1386 Play on Words(有向图欧拉路+并查集)

题目链接:http://poj.org/problem?id=1386

思路分析:该问题要求判断单词是否能连接成一条直线,转换为图论问题:将单词的首字母和尾字母看做一个点,每个单词描述了一条从首字母指向尾字母的有向边,

则则所有的单词构成了一个有向图,问题变为判断该有向图中是否存在一条欧拉路;有向图中存在欧拉路的两个充分必要条件为:该图是联通的并且所有的点的入度等于出度或者只存在两个点的入度与出度不等,一个点的入度=出度+1,另一个点的入度=出度-1;

代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

const int MAX_N = 30;
const int MAX_M = 1000 + 10;
int fa[MAX_N], show[MAX_N];
int in[MAX_N], out[MAX_N];
int set_visited[MAX_N];
char str[MAX_M];

void Init()
{
    for (int i = 0; i < MAX_N; ++i)
        fa[i] = i;
    memset(in, 0, sizeof(in));
    memset(out, 0, sizeof(out));
    memset(show, 0, sizeof(show));
    memset(set_visited, 0, sizeof(set_visited));
}

int Find(int a)
{
    if (fa[a] == a)
        return a;
    else
        return fa[a] = Find(fa[a]);
}

int Union(int a, int b)
{
    int fa_a = Find(a);
    int fa_b = Find(b);

    if (fa_a == fa_b)
        return -1;
    if (fa_a > fa_b)
        fa[fa_b] = fa_a;
    else
        fa[fa_a] = fa_b;
    return 1;
}

int main()
{
    int case_times, n, len;

    scanf("%d", &case_times);
    while (case_times--)
    {
        scanf("%d", &n);
        Init();
        for (int i = 0; i < n; ++i)
        {
            int l, r;

            scanf("%s", str);
            len = strlen(str);
            l = str[0] - ‘a‘;
            r = str[len - 1] - ‘a‘;
            in[l]++;
            out[r]++;
            show[l] = show[r] = 1;
            Union(l, r);
        }
        int set_count = 0;
        int not_equal = 0;
        int in_big_out = 0, out_big_in = 0;
        bool ok = true;
        for (int i = 0; i < MAX_N; ++i)
        {
            if (show[i])
            {
                int fa_i = Find(i);
                if (set_visited[fa_i] == 0)
                {
                    set_count++;
                    set_visited[fa_i] = 1;
                }
                if (set_count > 1)
                {
                    ok = false;
                    break;
                }
                if (in[i] != out[i])
                    not_equal++;
                if (in[i] == out[i] + 1)
                    in_big_out++;
                if (in[i] + 1 == out[i])
                    out_big_in++;
            }
        }

        if (!((not_equal == 0) || (out_big_in == 1 && in_big_out == 1
            && in_big_out + out_big_in == not_equal)))
            ok = false;

        if (ok)
            printf("Ordering is possible.\n");
        else
            printf("The door cannot be opened.\n");
    }
    return 0;
}
时间: 2024-10-24 05:05:45

poj 1386 Play on Words(有向图欧拉路+并查集)的相关文章

Catenyms+欧拉回路/欧拉路+并查集+POJ

Catenyms Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9617   Accepted: 2524 Description A catenym is a pair of words separated by a period such that the last letter of the first word is the same as the last letter of the second. For e

POJ 1386 Play on Words(欧拉路)

http://poj.org/problem?id=1386 题意: 给出多个单词,只有单词首字母与上一个单子的末尾字母相同时可以连接,判断所有字母是否可以全部连接在一起. 思路: 判断是否存在欧拉道路,每个单词只需要处理首字母和尾字母就可以了. 还有需要注意的就是需要判断图是否连通,我在这里用了并查集来判断. 有向图D存在欧拉道路的充要条件是:D为有向图,D的基图连通,并且所有顶点的出度与入度都相等:或者除两个顶点外,其余顶点的出度与入度都相等,而这两个顶点中一个顶点的出度与入度之差为1,另一

POJ 2337 &amp;&amp; ZOJ 1919--Catenyms 【有向图 &amp;&amp; 欧拉路判断 &amp;&amp; 欧拉路径】

Catenyms Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10427   Accepted: 2726 Description A catenym is a pair of words separated by a period such that the last letter of the first word is the same as the last letter of the second. For

poj 1386 Play on Words(有向图欧拉回路)

1 /* 2 题意:单词拼接,前一个单词的末尾字母和后一个单词的开头字母相同 3 思路:将一个单词的开头和末尾单词分别做两个点并建一条有向边!然后判断是否存在欧拉回路或者欧拉路 4 5 再次强调有向图欧拉路或欧拉回路的判定方法: 6 (1)有向图G为欧拉图(存在欧拉回路),当且仅当G的基图连通,且所有顶点的入度等于出度. 7 (2)有向图G为半欧拉图(存在欧拉道路),当且仅当G的基图连通,且存在顶点u的入度比出度大1.v的入度比出度小1, 8 其它所有顶点的入度等于出度(顶点u,v的个数必须都是

poj 2492 a bug&#39;s life 简单种类并查集

题意大致为找同性恋的虫子.... 这个比食物链要简单些.思路完全一致,利用取余操作实现关系之间的递推. 个人感觉利用向量,模和投影可能可以实现具有更加复杂关系的并查集. 1 #include<cstdio> 2 using namespace std; 3 const int MAXN=50010; 4 int fa[MAXN]; 5 int rel[MAXN]; // 0代表同类,1代表吃fa[i],2代表被吃 6 void _set(int n) 7 { 8 for(int i=1;i&l

POJ 1984 Navigation Nightmare 二维带权并查集

题目来源:POJ 1984 Navigation Nightmare 题意:给你一颗树 k次询问 求2点之间的曼哈顿距离 并且要在只有开始k条边的情况下 思路:按照方向 我是以左上角为根 左上角为原点 dx[i]为i点距离根的x坐标 dy[]是y坐标 这两个可以通过路径压缩求出 只不过是二维而已 #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int m

POJ 2492 || HDU 1829:A Bug&#39;s Life(并查集)

传送门: POJ:点击打开链接 HDU:点击打开链接 A Bug's Life Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 27624   Accepted: 8979 Description Background Professor Hopper is researching the sexual behavior of a rare species of bugs. He assumes that they fe

POJ 2492 A Bug&#39;s Life (带权并查集 &amp;&amp; 向量偏移)

题意 : 给你 n 只虫且性别只有公母, 接下来给出 m 个关系, 这 m 个关系中都是代表这两只虫能够交配, 就是默认异性, 问你在给出的关系中有没有与异性交配这一事实相反的, 即同性之间给出了交配关系. 分析 : 本题雷同POJ 1182 食物链, 如果会了那一题, 那现在这题便简单多了, 建议先了解食物链的偏移向量做法.这里也是使用向量的思考方式来进行relation的变化, 这里我令 relation = 0为同性, relation = 1为异性, 接下来的步骤就和食物链的雷同了. 优

POJ 1703 Find them, Catch them(数据结构-并查集)

Find them, Catch them Description The police office in Tadu City decides to say ends to the chaos, as launch actions to root up the TWO gangs in the city, Gang Dragon and Gang Snake. However, the police first needs to identify which gang a criminal b