hdu1116 Play on Words--并查集
原题链接: pid=1116">http://acm.hdu.edu.cn/showproblem.php? pid=1116
一:原题内容
There is a large number of magnetic plates on every door. Every plate has one word written on it. The plates must be arranged into a sequence in such a way that every word begins with the same letter as the previous word ends. For example, the word ``acm''
can be followed by the word ``motorola''. Your task is to write a computer program that will read the list of words and determine whether it is possible to arrange all of the plates in a sequence (according to the given rule) and consequently to open the door.
each containing a single word. Each word contains at least two and at most 1000 lowercase characters, that means only letters 'a' through 'z' will appear in the word. The same word may appear several times in the list.
several times must be used that number of times.
If there exists such an ordering of plates, your program should print the sentence "Ordering is possible.". Otherwise, output the sentence "The door cannot be opened.".
3
2
acm
ibm
3
acm
malform
mouse
2
ok
ok
The door cannot be opened.
Ordering is possible.
The door cannot be opened.
二:分析理解
题目大意:给你一些英文单词。推断全部单词能不能连成一串,类似成语接龙的意思。
可是假设有多个反复的单词时,也必须满足这种条件才干算YES。
否则都是不可能的情况。
解题思路:欧拉路的基本题。仅仅要知道就能够做出来了。
关于欧拉回路和欧拉路径
定义:
欧拉回路:每条边恰好仅仅走一次。并能回到出发点的路径
欧拉路径:经过每一条边一次。可是不要求回到起始点
①首先看欧拉回路存在性的判定:
一、无向图
每一个顶点的度数都是偶数,则存在欧拉回路。
二、有向图(全部边都是单向的)
每一个节顶点的入度都等于出度,则存在欧拉回路。
三.混合图欧拉回路
混合图欧拉回路用的是网络流。
把该图的无向边随便定向,计算每一个点的入度和出度。假设有某个点出入度之差为奇数,那么肯定不存在欧拉回路。由于欧拉回路要求每点入度 = 出度,也就是总度数为偶数,存在奇数度点必不能有欧拉回路。
好了,如今每一个点入度和出度之差均为偶数。
那么将这个偶数除以2。得x。也就是说。对于每一个点,仅仅要将x条边改变方向(入>出就是变入,出>入就是变出),就能保证出 = 入。假设每一个点都是出 = 入。那么非常明显。该图就存在欧拉回路。
如今的问题就变成了:我该改变哪些边,能够让每一个点出 = 入?构造网络流模型。首先,有向边是不能改变方向的,要之无用。删。
一開始不是把无向边定向了吗?定的是什么向,就把网络构建成什么样。边长容量上限1。另新建s和t。对于入 > 出的点u,连接边(u, t)、容量为x。对于出 > 入的点v,连接边(s, v),容量为x(注意对不同的点x不同)。
之后。察看是否有满流的分配。有就是能有欧拉回路。没有就是没有。
欧拉回路是哪个?查看流值分配,将全部流量非 0(上限是1,流值不是0就是1)的边反向,就能得到每点入度 =
出度的欧拉图。
因为是满流,所以每一个入 > 出的点,都有x条边进来,将这些进来的边反向。OK,入 = 出了。对于出 > 入的点亦然。
那么。没和s、t连接的点怎么办?和s连接的条件是出 > 入,和t连接的条件是入 > 出,那么这个既没和s也没和t连接的点。自然早在開始就已经满足入 = 出了。那么在网络流过程中,这些点属于“中间点”。
我们知道中间点流量不同意有累积的。这样。进去多少就出来多少,反向之后,自然仍保持平衡。
所以,就这样。混合图欧拉回路问题,解了。
②.欧拉路径存在性的判定
一。无向图
一个无向图存在欧拉路径。当且仅当 该图全部顶点的度数为偶数 或者 除了两个度数为奇数外其余的全是偶数。
二。有向图
一个有向图存在欧拉路径,当且仅当 该图全部顶点的度数为零 或者 一个顶点的度数为1,还有一个度数为-1,其它顶点的度数为0。
三。混合图欧拉路径
事实上整篇文章仅仅有这部分是我写的哈,灰常不好意思。仅仅是网上的同志们写的太好了。实在没有必要反复劳动,不知道大家有没有发现。求欧拉路径的第一步一定是求欧拉回路。在混合图上也不例外,怎样推断混合图欧拉回路问题的存在性呢?首先。我们用上文所说的方法推断该图是否存在欧拉回路,假设存在。欧拉路径一定存在。假设欧拉回路不存在,那么我们枚举欧拉路径的起点和终点,连接一条无向边。然后再用最大流推断是否存在欧拉回路就可以。
所以这道题的大题思路就是:
1.并查集推断连通
2.将每一个单词取出首字母和尾字母,转换为一条边,然后增加相应的连通分量中。
假设这个字母出现过。visit数组标记为true。同一时候起点出度加1。终点入度加1.
3.推断一下:
1)这个图必须是连通的,即根结点仅仅有一个。假设不是,直接结束本次算法。
2)假设这个图是连通的。推断每一个结点的入度和出度情况。
假设这个图是欧拉路,则每一个顶点的出度等于入度。
即out[i] = in[i]
假设这个图是半欧拉图。则起点的出度比入度大1。终点的入度比出度大1.其余顶点的出度等于入度。
假设满足上述条件,就能够将全部单词链接起来,否则不能。
当然。在推断出度入度的时候另一点须要注意,那就是除了起点终点以外的顶点。出度必须等于入度(出度入度能够同一时候为2。即环),可是起点和终点必须保证出度和入度之差为1。
三:AC代码
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 #include<iostream>
#include<string.h> using namespace std; char ch[1001]; //存储单词
int pre[27]; //一共26个英文字母。下标从1開始,用于并查集
int in[27]; //表示每一个单词的尾部字母的入度,默认是0
int out[27]; //表示每一个单词的头部字母的出度。默认是0
bool visited[27]; //字母是否出现。默认是false
int T; //測试实例个数
int N; //每一个实例要输入的单词的个数
int inNum; //推断出现的全部的字母,“入度减出度为1”的个数
int outNum; //推断出现的全部的字母,“出度减入度为1”的个数
int root; //根节点个数
bool flag; //推断出现的全部的字母的出度和入度之差是否是0或1,假设不是。那肯定不满足题意,还有推断root是否大于1,大于1的话。肯定不满足
int start;
int last; int Find(int x)
{
return (x != pre[x]) ? Find(pre[x]) : x;
} void Union(int x, int y)
{
int root_x = Find(x);
int root_y = Find(y); if (root_x != root_y)
pre[root_x] = root_y;
} int main()
{
cin >> T;
while (T--)
{
for (int i = 1; i < 27; i++)
pre[i] = i;
memset(in, 0, sizeof(in));
memset(out, 0, sizeof(out));
memset(visited, 0, sizeof(visited)); inNum = outNum = root = 0;
flag = true; cin >> N;
for (int i = 0; i < N; i++)
{
cin >> ch;
int len = strlen(ch); start = ch[0] - 'a' + 1;
last = ch[len - 1] - 'a' + 1; visited[start] = true;
visited[last] = true;
out[start]++;
in[last]++; Union(start, last);
} for (int i = 1; i <= 26; i++)
{
if (visited[i])
{
if (pre[i] == i)
root++;
if (out[i] != in[i])//注意点
{
if (out[i] - in[i] == 1)
outNum++;
else if (in[i] - out[i] == 1)
inNum++;
else
flag = false;
}
} if (!flag)
break;
if (root > 1)
{
flag = false;
break;
}
} if ((flag&&inNum == 0 && outNum == 0) || (flag&&inNum == 1 && outNum == 1))
cout << "Ordering is possible.\n";
else
cout << "The door cannot be opened.\n";
} return 0;
}
參考 :http://www.acmerblog.com/hdu-1116-play-on-words-1412.html
hdu1116 Play on Words--并查集的更多相关文章
- HDU1116(欧拉路径+并查集)
题意: 给出一些字符串,有这两个字符串,如果第一个字符串的最后一个字母和第二个字符串的第一个字母是一样的,则这两个字符串是可以连接在一起的. 问给出的这些字符串能否串成一个环或者一整个链. 思路: 将 ...
- BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]
4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...
- 关押罪犯 and 食物链(并查集)
题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值"( ...
- 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用
图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...
- bzoj1854--并查集
这题有一种神奇的并查集做法. 将每种属性作为一个点,每种装备作为一条边,则可以得到如下结论: 1.如果一个有n个点的连通块有n-1条边,则我们可以满足这个连通块的n-1个点. 2.如果一个有n个点的连 ...
- [bzoj3673][可持久化并查集 by zky] (rope(可持久化数组)+并查集=可持久化并查集)
Description n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0& ...
- [bzoj3123][sdoi2013森林] (树上主席树+lca+并查集启发式合并+暴力重构森林)
Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...
- 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集
3673: 可持久化并查集 by zky Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 1878 Solved: 846[Submit][Status ...
- Codeforces 731C Socks 并查集
题目:http://codeforces.com/contest/731/problem/C 思路:并查集处理出哪几堆袜子是同一颜色的,对于每堆袜子求出出现最多颜色的次数,用这堆袜子的数目减去该值即为 ...
随机推荐
- Git系列学习(1)-Git安装
一.概述 msysGit名字前面的四个字面来源于MSYS项目: MSYS项目来源于MinGW(Minimalist GNU for Windows,最简GNU工具集) 通过添加一个bash提供的she ...
- Jquery EasyUI环境下设置下拉框选中指定选项
前提: 要求点击某个按钮就将所有的下拉框都设置为选中第一个选项,因此,指定索引是最好的做法 尝试过的做法: html代码如下(easyui 的写法) <select class="ea ...
- JS高级——apply与call
上下文调用模式 可以修改this的值,也就是可以修改函数的调用方式,apply.call可以修改函数调用上下文,也就是this的值 <script> var name = "莱昂 ...
- django 加日志
LOGGING = { 'version': 1, 'disable_existing_loggers': False, # 指定输出的格式,被handler使用. 'formatters': { ' ...
- element ui 日期控件范围时间限制记录、以及计算两个日期之间的天数
日期的筛选经常会有最小的日期选择,例如:当前日期 :clearable="false" :picker-options="pickerOptions0" val ...
- SweetAlert弹出框
以前也用过,那个时候没有写过,突然看见了,就写上了. 网址:http://mishengqiang.com/sweetalert2/ swal({ title: '确定删除吗?', text: '你将 ...
- include和require区别
1. include()执行的时候需要引用的文件每次都要进行读取评估; require()执行时需要引用的文件只处理一次(实际上执行时需要引用的文件内容替换了require()语句) 可以看出若有包 ...
- php第十二节课
练习 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.o ...
- [Luogu] P4198 楼房重建
题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些事件发生在一个 ...
- Oracle存储过程及函数的练习题
--存储过程.函数练习题 --(1)创建一个存储过程,以员工号为参数,输出该员工的工资create or replace procedure p_sxt1(v_empno in emp.empno%t ...