判断欧拉路径是否存在及求出字典序最小的欧拉路径问题(如果存在)。

将字符串的第一个字母和最后一个字母间连边,将字母看成点,最多可能有26个点(a-z),如果有欧拉路径,还要判断是否有欧拉回路,如果有,则需要找一个字典序最小的点开始生成这条链,否则以起点开始生成链,起点即为出度比入度大1的点。

欧拉路径是否存在的判定:

1.全部点在一个联通块                               ----用并查集判联通块的数量
2.所有点出度入度相等                               ----in[],out[]记录出度与入度
3.或者有一个出度比入度小1,另一个出度比入度大1(源点与汇点)

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#define Mod 1000000007
using namespace std;
#define N 2007 string ss[N]; struct node
{
int u,v,next;
string w;
}G[N]; int first[],fa[],in[],out[],vis[];
int tot,k,start;
int evis[N];
string ans[N]; void init()
{
int i;
for(i=;i<;i++)
fa[i] = i;
tot = ;
memset(in,,sizeof(in));
memset(out,,sizeof(out));
for(i=;i<=;i++)
{
G[i].u = G[i].v = G[i].next = ;
G[i].w = "";
}
memset(first,-,sizeof(first));
memset(vis,,sizeof(vis));
memset(evis,,sizeof(evis));
for(int j=;j<=;j++)
ans[j] = "";
} int findset(int x)
{
if(x != fa[x])
fa[x] = findset(fa[x]);
return fa[x];
} int cmp(string ka,string kb)
{
return ka>kb;
} void addedge(int u,int v,string w)
{
G[tot].u = u;
G[tot].v = v;
G[tot].w = w;
G[tot].next = first[u];
first[u] = tot++;
out[u]++;
in[v]++;
vis[u] = vis[v] = ;
int fx = findset(u);
int fy = findset(v);
if(fx != fy)
fa[fx] = fy;
} int Euler_Path()
{
int block = ,i;
int O = ;
int I = ;
start = -;
for(i=;i<;i++)
{
if(vis[i]) //涉及到的字母
{
int fk = findset(i);
if(fk == i)
block++;
if(block > )
return false;
if(in[i] == out[i]+) //入大出,奇度数点
I++;
else if(in[i]+ == out[i]) //出大入,奇度数点
O++,start = i;
else if(in[i] != out[i])
return false;
}
}
if(block != )
return false;
if((O == I && O == ) || (O == I && O == )) //没有奇度数点或者只有源点和汇点是奇度数点
{
if(start == -) //没有找到起点,是欧拉回路
{
for(i=;i<;i++)
{
if(vis[i] && out[i] > ) //找字典序最小的字母做起点
{
start = i;
return true;
}
}
}
//如果已找到起点,则不能是欧拉回路
if(O == I && O == )
return true;
return false;
}
return false;
} void dfs(int v,int flag)
{
for(int e=first[v];e!=-;e=G[e].next)
{
if(!evis[e]) //边没被访问
{
evis[e] = ;
dfs(G[e].v,e);
}
}
if(flag != -)
ans[k++] = G[flag].w;
} int main()
{
int t,i,j,n;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d",&n);
for(i=;i<=n;i++)
cin>>ss[i];
sort(ss+,ss+n+,cmp);
//qsort(ss+1,n,28,cmp);
for(i=;i<=n;i++)
{
int u = ss[i][]-'a';
int v = ss[i][ss[i].length()-]-'a';
addedge(u,v,ss[i]);
}
if(Euler_Path())
{
k = ;
dfs(start,-);
cout<<ans[k-];
for(i=k-;i>=;i--)
cout<<"."<<ans[i];
printf("\n");
}
else
puts("***");
}
return ;
}

UESTC 917 方老师的分身IV --求欧拉路径的更多相关文章

  1. UESTC 901 方老师抢银行 --Tarjan求强连通分量

    思路:如果出现了一个强连通分量,那么走到这个点时一定会在强连通分量里的点全部走一遍,这样才能更大.所以我们首先用Tarjan跑一遍求出所有强连通分量,然后将强连通分量缩成点(用到栈)然后就变成了一个D ...

  2. UESTC 914 方老师的分身I Dijkstra

    题意:求有向图的往返最短路的最长长度. 分析:求第一次到所有点的距离可以用一次Dijkstra求最短路求出来.考虑回来的路,想想就知道,从每个点回来的路即为将边的方向反转再求一次最短路后的结果. 所以 ...

  3. UESTC 915 方老师的分身II --最短路变形

    即求从起点到终点至少走K条路的最短路径. 用两个变量来维护一个点的dis,u和e,u为当前点的编号,e为已经走过多少条边,w[u][e]表示到当前点,走过e条边的最短路径长度,因为是至少K条边,所以大 ...

  4. UESTC 916 方老师的分身III --拓扑排序

    做法: 如果有a<b的关系,则连一条a->b的有向边,连好所有边后,找入度为0的点作为起点,将其赋为最小的价值888,然后其所有能到的端点,价值加1,加入队列,删去上一个点,然后循环往复, ...

  5. UESTC_方老师的分身 II CDOJ 915

    方老师的分身 II Time Limit: 10000/5000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submi ...

  6. UESTC 898 方老师和缘分 --二分图匹配+强连通分量

    这题原来以为是某种匹配问题,后来好像说是强连通的问题. 做法:建图,每个方老师和它想要的缘分之间连一条有向边,然后,在给出的初始匹配中反向建边,即如果第i个方老师现在找到的是缘分u,则建边u-> ...

  7. UESTC - 900 方老师炸弹 —— 割点

    题目链接:https://vjudge.net/problem/UESTC-900   方老师炸弹 Time Limit: 4000/2000MS (Java/Others)     Memory L ...

  8. UESTC 900 方老师炸弹 --Tarjan求割点及删点后连通分量数

    Tarjan算法. 1.若u为根,且度大于1,则为割点 2.若u不为根,如果low[v]>=dfn[u],则u为割点(出现重边时可能导致等号,要判重边) 3.若low[v]>dfn[u], ...

  9. UESTC 884 方老师的专题讲座 --数位DP

    定义:cnt[L][K]表示长度为L,最高位为K的满足条件C的个数. 首先预处理出cnt数组,枚举当前长度最高位和小一个长度的最高位,如果相差大于2则前一个加上后一个的方法数. 然后给定n,计算[1, ...

随机推荐

  1. 【译】Dependency Injection with Autofac

    先说下为什么翻译这篇文章,既定的方向是架构,然后为了学习架构就去学习一些架构模式.设计思想. 突然有一天发现依赖注入这种技能.为了使得架构可测试.易维护.可扩展,需要架构设计为松耦合类型,简单的说也就 ...

  2. js一些小题(二)

    ******************************************************************* 一个全局下的函数: function test() { aler ...

  3. 微信公共平台开发5 .net

    每次在于微信交互时,都要用到access_token,但是这个值限制的是有时间的,但是access_token,在以后的高级功能里面会经常用到,所以这里不得不这里对前面所讲解的access_token ...

  4. Form.action传值问题

    通过浏览器地址栏输入url并通过?传递参数请求资源时,?后面的参数叫做 "查询字符串",会触发后台Servlet的doGet(),因为通过浏览器地址栏直接访问的方式是GET方式. ...

  5. lazyload.js详解

    简介 lazyload.js用于长页面图片的延迟加载,视口外的图片会在窗口滚动到它的位置时再进行加载,这是与预加载相反的. 优点: 它可以提高页面加载速度: 在某些情况清晰它也可以帮助减少服务器负载. ...

  6. .NET破解之分享给新注册的朋友

    前些日子,在论坛里看了有人发过这个软件,也有大神分析过网络版,如果是重帖,请删除吧:正好11.11注册了很多新会员,给他们一个见面礼吧,抛砖引玉,我才来论坛的时候,也是看着前人教程慢慢学习的:好久没冒 ...

  7. Creating a SharePoint BCS .NET Connectivity Assembly to Crawl RSS Data in Visual Studio 2010

    from:http://blog.tallan.com/2012/07/18/creating-a-sharepoint-bcs-net-assembly-connector-to-crawl-rss ...

  8. Android源码分析之SparseArray

    本来接下来应该分析MessageQueue了,可是我这几天正好在实际开发中又再次用到了SparseArray(之前有用到过一次,那次只是 大概浏览了下源码,没做深入研究),于是在兴趣的推动下,花了些时 ...

  9. 【AdaBoost算法】积分图代码实现

    一.积分图介绍 定义:图像左上方的像素点值的和: 在Adaboost算法中可用于加速计算Haar或MB-LBP特征值,如下图: 二.代码实现 #include <opencv/highgui.h ...

  10. LINQ SQL分组取最近一条记录

    最近项目有一个需求,从订单表查询出每个客户最近一条订单记录.数据库表结构如下图 SELECT * FROM ( select ROW_NUMBER()over(partition by [custid ...