poj2337

这道题昨天晚上开始做,今天才A。但是问题想透了, 发现其实没那么难

题目大意: 
给你一些单词,如果一个单词的末尾字符与另一个单词首字符相同,则两个的单词可以连接。问是否可以把所有单词连接起来,并且每个单词只能用一次。 
分析: 
可以把每个单词看成是一条边,单词的首尾字符看做是两个相连的点。我们可以把它看成有向图的欧拉路径问题(欧拉路径,欧拉回路不太明白的自己百度吧)。 
一个有向图含有欧拉通路,首先图是连通的,并且当且仅当该图所有顶点的入度 =出度, 或者起始顶点入度 = 出度 - 1 ,结束点 出度=入度-1, 其余点入度= 出度。明白了这些,我们的思路也就清晰啦! 
重点来啦:首先判断图是否连通的,在判断图是否存在欧拉路径,如果都符合那就找路径。

#include<iostream>
#include<cstdio>
#include<string.h>
#include<cstring>
#include<algorithm>
using namespace std; int out[], in[], step[], pre[];
int n, k, t, st;
char w[]; struct Edge//结构体:边, 存储了边的起点(首字符)和终点(尾字符),状态(是否走过)
{
int s, e, v;
char c[];
}edge[]; bool cmp(Edge x, Edge y)
{
return strcmp(x.c, y.c) < ? true : false;
}
int find(int x)//查找其父节点
{
if(pre[x] != x)
pre[x] = find(pre[x]);
return pre[x];
}
int panduan()//判断是否图是连通的
{
int fx = find(edge[].s);
for(int i = ; i <= ; i++)
{
if(out[i] > || in[i] > )
{
if(find(i) != fx)
return ;
}
}
return ;
}
void path(int en)//查找路径
{
for(int i = ; i <= n; i++)
{
if(edge[i].v == && edge[i].s == en)
{
edge[i].v = ;
path(edge[i].e);
step[++k] = i;
}
}
}
int main()
{
cin >> t;
while(t--)
{
memset(out, , sizeof(out));
memset(in, , sizeof(in));
memset(step, , sizeof(step));
for(int i = ; i <= ; i++)
pre[i] = i;
scanf("%d", &n);
for(int i = ; i <= n; i++)
{
cin >> w;
int len = strlen(w);
int s = w[] - 'a' + ;
int e = w[len - ] - 'a' + ;
edge[i].s = s;
edge[i].e = e;
strcpy(edge[i].c, w);
edge[i].v = ; out[s]++;
in[e]++;
/*如果存在欧拉路径,那么所有的点一定都连通.所有的点都在一个集合里,可以用并查集知识
将所有连接的点并到一起。*/
int fx = find(s);
int fy = find(e);
if(fx != fy)
pre[fx] = fy;
}
sort(edge + , edge + + n, cmp);//题目要求字典序最小输出,就先按从小到大的顺序把边(单词)排好
/*st代表的是路径起点,在这里进行st = edge[1].s赋值,是应为存在两种情况:1.存在一定点出度>入度,
这个点是起点。2.所有点出度= 入度, 那么从任意一点出发都可以, 为了保证字典序最小, 就从第一个单词开始*/
st = edge[].s;
int i, c1 = , c2 = ;
for(i = ; i <= ; i++)//判断是否有欧拉回路
{
if(out[i] == in[i])continue;
else if(in[i] == out[i] - ) {c1++; st = i;}//起点
else if(in[i] == out[i] + ) c2++;
else break;
}
//如果符合了连通图,并且存在欧拉通路, 就开始找路径
if(i == && ((c1 == c2 && c1 == ) || (c1 == c2 && c1 == )) && panduan() == )
{
k = ;
path(st);
for(int i = n; i > ; i--)//输出这注意点,因为是递归求的路径, 最先得到的是最后的边
printf("%s.", edge[step[i]].c);
printf("%s\n", edge[step[]].c);
}
else
printf("***\n");
}
return ;
}

poj2337 欧拉路径的更多相关文章

  1. POJ2337 欧拉路径字典序输出

    题意:       给一些单词,问是否可以每个单词只用一次,然后连接在一起(不一定要成环,能连接在一起就行). 思路:       这个题目的入手点比较好想,其实就是问欧拉路径,先说下解题步骤,然后在 ...

  2. 有向图的欧拉路径POJ2337

    每个单词可以看做一条边,每个字母就是顶点. 有向图欧拉回路的判定,首先判断入度和出度,其实这个题判定的是欧拉通路,不一定非得构成环,所以可以有一个点的顶点入度比出度大1,另外一个点的出度比入度大1,或 ...

  3. POJ 2337 Catenyms (有向图欧拉路径,求字典序最小的解)

    Catenyms Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8756   Accepted: 2306 Descript ...

  4. 【USACO 3.3】Riding The Fences(欧拉路径)

    题意: 给你每个fence连接的两个点的编号,输出编号序列的字典序最小的路径,满足每个fence必须走且最多走一次. 题解: 本题就是输出欧拉路径. 题目保证给出的图是一定存在欧拉路径,因此找到最小的 ...

  5. hdu 3472 HS BDC(混合路的欧拉路径)

    这题是混合路的欧拉路径问题. 1.判断图的连通性,若不连通,无解. 2.给无向边任意定向,计算每个结点入度和出度之差deg[i].deg[i]为奇数的结点个数只能是0个或2个,否则肯定无解. 3.(若 ...

  6. poj 2337 有向图输出欧拉路径

    Catenyms Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10186   Accepted: 2650 Descrip ...

  7. nyoj 42 一笔画问题 欧拉路径

    题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=42 欧拉回路,欧拉路径水题~ 代码: #include "stdio.h&quo ...

  8. UESTC 917 方老师的分身IV --求欧拉路径

    判断欧拉路径是否存在及求出字典序最小的欧拉路径问题(如果存在). 将字符串的第一个字母和最后一个字母间连边,将字母看成点,最多可能有26个点(a-z),如果有欧拉路径,还要判断是否有欧拉回路,如果有, ...

  9. POJ1780 Code(欧拉路径)

    n位密码,要用尽可能短的序列将n位密码的10n种状态的子串都包括,那么要尽量地重合. 题目已经说最短的是10n + n - 1,即每一个状态的后n-1位都和序列中后一个状态的前n-1位重合. 这题是经 ...

随机推荐

  1. 查找进程对应的PID和对应的端口号

    第一步:首先打开任务管理器.之后左键单击查看,点击下面的选择列. 第二步:之后进入如下界面,把PID勾上.这是我们就可以查看到进程的PID(process id)号了 第三步:首先我们打开DOS窗口, ...

  2. 【C语言】-循环结构-for语句

    for语句: for (表达式1;表达式2;表达式3) { 循环语句 } 表达式1 给循环变量赋初值 表达式2 为循环条件 表达式3 用来修改循环变量的值,称为循环步长. for语句的执行流程: 例: ...

  3. [iOS基础控件 - 5.1] UIScrollView

    A.需要掌握 UIScrollView 是一个能够滚动的视图控件,可以用来展示大量内容,如手机的“设置” 1.常见属性 2.常用代理方法 3.缩放 4.UIScrollView和UIPageContr ...

  4. [iOS基础控件 - 3.5] NSBundle, UIImageView和UIButton的区别, 模拟器和文档

    1.NSBundle1> 一个NSBundle代表一个文件夹,利用NSBundle能访问对应的文件夹2> 利用mainBundle就可以访问软件资源包中的任何资源3> 模拟器应用程序 ...

  5. Objective-C Runtime 运行时之三:方法与消息

    基础数据类型 SEL SEL又叫选择器,是表示一个方法的selector的指针,其定义如下: typedef struct objc_selector *SEL; objc_selector结构体的详 ...

  6. .NET设计模式(3):抽象工厂模式(Abstract Factory)

    ):抽象工厂模式(Abstract Factory) 抽象工厂模式(Abstract Factory) --探索设计模式系列之三 Terrylee,2005年12月12日 转载:http://terr ...

  7. jsp应用bootstrap表格应用实例

    一.初始化表格 <div style="margin-top: 80px;margin-left:45px;margin-right:30px;overflow-x: scroll&q ...

  8. SQLite使用教程5 分离数据库

    http://www.runoob.com/sqlite/sqlite-detach-database.html SQLite 分离数据库 SQLite的 DETACH DTABASE 语句是用来把命 ...

  9. 【转】C++及java在内存分配上的区别

    转自:http://blog.csdn.net/qinghezhen/article/details/9116053 C++内存分配由五个部分组成:栈.堆.全局代码区.常量区.程序代码区.如下图所示: ...

  10. android自动打包方法(ant+proguard+签名)

    前段时间做了一个android的网游项目,现在优化减少体积和防止别人反编译,需要把编译后.class进行混淆,开始在网上看了一些关于 ProGuard的介绍,基本上都是使用ADT自带的打包方式,那个打 ...