POJ 2337 Catenyms (欧拉图)
本文链接http://i.cnblogs.com/EditPosts.aspx?postid=5402042
题意:
给你N个单词,让你把这些单词排成一个序列,使得每个单词的第一个字母和上一个字单词的最后一个字母相同(栗如:acm,malform,mouse),每个单词最多包含20个小写字母,最多1000个单词。让你输出这个序列,每两个单词之间有个'.',如果有多个解,输出字典序最小的那组解,如果无解输出"***"。关于字典序,个人感觉就是把最后的序列包括'.'在内看成一个字符串,来比较字典序。举个栗子:aa.ab.ba.aba 的字典序小于 aa.aba.ab.ba因为在索引为 5 的地方第一个序列的'.'小于第二个序列的'a',而不是仅仅看每个单词的第一个字母。
思路:
把每个单词的的两端看成点,把单词看成一条有向边,栗如 atob 表示点 a 到点 b 有一条有向边。那么如果问题有解,则图中一定存在欧拉通路。所以需要首先判断底图是否存在欧拉通路,由单词所建立起来的图是一个有向图,判断有向图是否存在欧拉通路的条件有两个:
第一:底图必须连通,可以用并查集判断;
第二:可以存在2个点出度不等于入度,这两个点中一个出度比入度大1,为路径的起点,另外一个,入度比出度大1,为路径的终点。
如果满足上述两个条件,下来就需要找欧拉路径了,可以采用套圈法, 由于要输出字典序,所以需要对所有单词进行排序,由于涉及到排序,刚好可以用前向星来存储图。
注意:
第一点:把单词看成边一定是有向的,判定条件不要和无向图搞混。
第二点:提前排好序,不要在每次选择扩展路径时才选择字典序最小的,容易TLE。
第三点:如果按照从升序,那么答案应该是反过来的,存在栈中就行了。
第四点:题目中给的单词是随机的,所以需要找到起点,如果图中存在欧拉回路,即所有点的入度等于出度,那么找到出现的单词中首字母最小的就可以作为路径的起点了。如果不存在欧拉回路,仅存在欧拉通路,即存在确定的起点和确定的终点,那么起点不应该是字母最小的点了,而是确定的那个起点,即出度比入度大 1 的点。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
using namespace std; const int maxV = ;
const int maxE = ;
int indeg[maxV + ];//入度
int outdeg[maxV + ];//出度
int head[maxV + ];//确定起点为vi的第一条边的位置
int pre[maxV + ];
int vis[maxE + ];
int E, V;
//并查集
void initPre()
{
for(int i = ; i <= maxV; i++)pre[i] = i;
} int Find(int x)
{
return x == pre[x] ? x : pre[x] = Find(pre[x]);
} void mix(int x, int y)
{
int fx = Find(x);
int fy = Find(y);
if(fx > fy) pre[fx] = fy;
if(fx < fy) pre[fy] = fx;
}
//前向星的结构
struct EdgeNode
{
int from;
int to;
char w[];//单词
}edges[maxE + ]; int minst;
bool isEuler()//是否能形成欧拉通路
{
int flag1 = ;
int flag2 = ;
for(int i = ; i <= maxV; i++)
{
if(indeg[i] != outdeg[i])
{
if(indeg[i] == outdeg[i] + ) flag1++;
else if(indeg[i] == outdeg[i] - ) flag2++,minst = i;//如果存在出度比入度大 1 的点,即为起点
else return false;
}
}
if(flag1 == && flag2 == || flag1 == && flag2 == ) return true;
return false;
} bool isConnct()//连通性判断
{
int cnt = ;
for(int i = ; i <= maxV; i++)
if( (outdeg[i] != || indeg[i] != ) && pre[i] == i)
cnt++;
if(cnt == )return true;
return false;
} stack<int> ans;
void eulerDFS(int now)
{
for(int k = head[now]; edges[k].from == now && k <= E; k++)//优先访问由字典序比较小的单词构成的边
{
if(!vis[k])
{
vis[k] = ;
eulerDFS(edges[k].to);
ans.push(k); //回溯时,压入栈的一定是字典序较大的
}
}
} int cmp(EdgeNode A, EdgeNode B)
{
return strcmp(A.w, B.w) < ;
} int main()
{
int T;
scanf("%d", &T);
while(T--)
{
memset(&edges, , sizeof(EdgeNode));
memset(indeg, , sizeof(indeg));
memset(outdeg, , sizeof(outdeg));
memset(vis, , sizeof(vis));
initPre();
scanf("%d", &E);
minst = maxV + ;
for(int i = ; i <= E; i++)
{
scanf("%s", edges[i].w);
edges[i].from = edges[i].w[] - 'a' + ;
edges[i].to = edges[i].w[strlen(edges[i].w) - ] - 'a' + ;
outdeg[edges[i].from]++;
indeg[edges[i].to]++;
mix(edges[i].from, edges[i].to);
minst = min(minst, edges[i].from);//默认首字母较小的为起点
}
sort(edges + , edges + E + , cmp);//按照字典序升序排序
memset(head, -, sizeof(head));
head[edges[].from] = ;
for(int i = ; i<= E; i++)//构造head数组
{
if(edges[i].from != edges[i - ].from) head[edges[i].from] = i;
}
if(isEuler() && isConnct())
{
eulerDFS(minst);
int flag = ;
while(!ans.empty())
{
printf((flag++) ? ".%s":"%s", edges[ans.top()].w);
ans.pop();
}
printf("\n");
}
else
printf("***\n");
}
return ;
}
POJ 2337 Catenyms (欧拉图)的更多相关文章
- POJ 2337 Catenyms(有向欧拉图:输出欧拉路径)
题目链接>>>>>> 题目大意: 给出一些字符串,问能否将这些字符串 按照 词语接龙,首尾相接 的规则 使得每个字符串出现一次 如果可以 按字典序输出这个字符串 ...
- POJ 2337 Catenyms
http://poj.org/problem?id=2337 题意: 判断给出的单词能否首尾相连,输出字典序最小的欧拉路径. 思路: 因为要按字典序大小输出路径,所以先将字符串排序,这样加边的时候就会 ...
- POJ 2337 Catenyms(欧拉回(通)路:路径输出+最小字典序)
题目链接:http://poj.org/problem?id=2337 题目大意:给你n个字符串,只有字符串首和尾相同才能连接起来.请你以最小字典序输出连接好的单词. 解题思路:跟POJ1386一个意 ...
- poj 2337 Catenyms 【欧拉路径】
题目链接:http://poj.org/problem?id=2337 题意:给定一些单词,假设一个单词的尾字母与还有一个的首字母同样则能够连接.问能否够每一个单词用一次,将全部单词连接,能够则输出字 ...
- POJ 2337 Catenyms (有向图欧拉路径,求字典序最小的解)
Catenyms Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8756 Accepted: 2306 Descript ...
- POJ 2337 Catenyms (欧拉回路)
Catenyms Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8173 Accepted: 2149 Descript ...
- POJ 2337 Catenyms(有向图的欧拉通路)
题意:给n个字符串(3<=n<=1000),当字符串str[i]的尾字符与str[j]的首字符一样时,可用dot连接.判断用所有字符串一次且仅一次,连接成一串.若可以,输出答案的最小字典序 ...
- Poj 2337 Catenyms(有向图DFS求欧拉通路)
题意: 给定n个单词, 问是否存在一条欧拉通路(如acm,matal,lack), 如果存在, 输出字典序最小的一条. 分析: 这题可以看作http://www.cnblogs.com/Jadon97 ...
- Day 4 -E - Catenyms POJ - 2337
A catenym is a pair of words separated by a period such that the last letter of the first word is th ...
随机推荐
- DataGridView重查后,返回原来所在行
首先记录选中行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 //查询前记录选中行 int _currentRow = 0; //int _cu ...
- http协议--留
1.http消息结构 *http客户端,即web浏览器,链接到服务器,向服务器发送一个http请求的目的 *http服务器,即web服务,接受请求,并向客户端发送http响应数据 http统一资源标识 ...
- JDK从1.8升级到9.0.1后sun.misc.BASE64Decoder和sun.misc.BASE64Encoder不可用
目录 描述 原因分析 处理办法 参考 描述 最近研究把项目的JDK升级从1.8升级到9.0.1,在eclipse上配置好JDK为9后,发现项目有错,查看发现sun.misc.BASE64Decoder ...
- php 值传递和引用传递的区别
值传递:函数范围内对值的任何改变在函数外部都会被忽略 引用传递:函数范围内对值的任何改变在函数外部也能反映出这些修改 A:按值传递时,php必须复制值.特别是对于大型的字符串和对象来说,这将会是一个代 ...
- CF 1103B Game with modulo
题目 $a, x$ 是正整数.显然有 \begin{aligned} x \ge 2x \pmod{a} \implies a \le 2x \end{aligned} 若 $x \le a$ 则 \ ...
- BFC,IFC,GFC,FFC
FC的全称是:Formatting Contexts,是W3C CSS2.1规范中的一个概念.它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用. ...
- WebRTC 视频对话
今天聊一下WebRTC.很多开发者,可能会觉得有些陌生,或者直接感觉繁杂.因为WebRTC在iOS上的应用,只是编译都让人很是头痛.这些话,到此为止,以防让了解者失去信心.我们只传播正能量,再多的困难 ...
- 快速配置vim+ctags+taglist
实验平台:centos 7 1.安装vim编辑器 点击(此处)折叠或打开 $sudo yum install vim 并编辑配置文件.vimrc文件,放在主目录下/home/developer 参考配 ...
- 几个简单的VBS脚本程序以及其JS实现
1 语音发声脚本,调用sapi.spvoice读英语hh 保存为say.vbs,点击打开就可以念诗: set objTTS = CreateObject("sapi.spvoice&quo ...
- "todoList妙味"学习总结
1.v-bind 主要用于属性绑定 :class="{completed: item.isChecked}",它会将{}里面的内容解析为js表达式 2.vue提供了一组方法, ...