杭电1116Play on Words(欧拉路径(回路)的判断)

->题目请戳这里<-

题目大意:给你一些单词,问是否能完成单词接龙,即一个单词的最后一个字母是另一个单词的首字母,每个单词都必须有,并且只能出现一次。

题目分析:每个单词只取首尾字母,从首字母到尾字母建一条有向边,最后建成一张有向图,题目转化成了在这张有向图中能否找到一条欧拉路径或者回路。用并查集维护这张图可以判断图是否连通。

来复习一下欧拉图的判断条件:

1。对于无向图,每个顶点的度数为偶数=>存在欧拉回路;如果恰有2个点度数为奇数=>存在欧拉路径,这2个度数为奇数的点为起点和终点。

2。对于有向图,每个顶点的入度=出度=>存在欧拉回路;如果恰有2个点入度与出度之差恰为1=>存在欧拉路径,出度比入度大一的点为起点,另一个为终点。

当然,以上2中情况都是在保证图连通的前提下的。其他情况都不满足。

详情请见代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int N = 100005;
int in[30],out[30];
int set[30];
char s[1005];
int n;
int cnt;

void init()
{
    int i;
    for(i = 1;i <= 26;i ++)
    {
        set[i] = i;
        in[i] = out[i] = 0;
    }
}

int find(int a)
{
    int root = a;
    while(root != set[root])
        root = set[root];
    int parent = set[a];
    while(parent != root)
    {
        set[a] = root;
        a = parent;
        parent = set[a];
    }
    return root;
}

void join(int a,int b)
{
    int root_a = find(a);
    int root_b = find(b);
    if(root_a == root_b)
        return;
    set[root_b] = root_a;
}

int isok()
{
    int odd = 0;
    int root = 0;
    int i;
    int tag = 0;
    for(i = 1;i <= 26;i ++)
    {
        if(set[i] == i && (in[i] + out[i]))
            root ++;
        if(root > 1)
            return 0;
    }
    for(i = 1;i <= 26;i ++)
    {
        if(in[i] == out[i])
            continue;
        else
        {
            if(abs(in[i] - out[i]) == 1)
                odd ++;
            else
                tag ++;
        }
    }
    if(tag)
        return 0;
    if(odd)
    {
        if(odd != 2)
            return 0;
    }
    return 1;
}

int main()
{
    int i,t;
    int len;
    int a,b;
    scanf("%d",&t);
    while(t --)
    {
        scanf("%d",&n);
        init();
        int nn = n;
        while(nn --)
        {
            scanf("%s",s);
            len = strlen(s);
            a = s[0] - 96;
            b = s[len - 1] - 96;
            out[a] ++;
            in[b] ++;
            join(a,b);
        }
        if(isok())//判断是否连通,是否存在欧拉路径(回路)
        {
            printf("Ordering is possible.\n");
        }
        else
            printf("The door cannot be opened.\n");
    }
    return 0;
}
//218MS	1468K
/*
10
1
abc
4
ab
ba
ef
fe
2
acm
ibm
3
acm
malform
mouse
2
ok
ok
*/


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值