您的位置:首页 > 其它

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

2013-06-06 16:45 477 查看
->题目请戳这里<-

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

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

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

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
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  图论 杭电