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

将字符串的第一个字母和最后一个字母间连边,将字母看成点,最多可能有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. ThinkPHP去掉URL中的index.php

    我的环境是apache+ubuntu 1,先确认你有没mod_rewrite.so模块 /usr/lib/apache2/modules/mod_rewrite.so 然后在httpd.conf最后一 ...

  2. [WF] Quickstart Sample

    [WF] Quickstart Sample 前言 Workflow Foundation(WF),总是给人一种很有用.可是却不知道怎么用的印象.这主要是因为前置的功课太多.要整合很多底层知识,才能完 ...

  3. [Windows Phone] APP上架,遇到错误2001的解决方案。(Error:2001)

    [Windows Phone] APP上架,遇到错误2001的解决方案.(Error:2001) 问题情景 最近在开始玩Windows Phone的开发,开发的过程中虽然有点小挫折,但是参考网络许多前 ...

  4. javascript函数中的三个技巧【一】

    在学习javascript中,函数是非常重要的,现在我来谈谈对函数的理解以及在工作和用法中的一些技巧 技巧一. [作用域安全的构造函数] 构造函数其实就是一个使用new操作调用的函数 function ...

  5. BINARY SEARCH in read table statement

    1.for standard table, it must be sorted by search key. 2.for sorted table , binary search is used au ...

  6. C#知识点总结【2】

    此文章只是 记录在C#当中一些我个人认为比较重要的知识点,对于有些基础实现或者用法并未说明: 继承 C#当中可以实现两种继承方式 1.实现继承:一个类派生于一个类,它拥有基类的所有成员字段和函数. 2 ...

  7. java多线程系列4-线程池

    在之前的文章中,学习了通过实现java.lang.Runnable来定义类,以及像下面这样创建一个线程来运行任务: Runnable task = new TaskClass(task); new T ...

  8. MyBatis入门(六)---mybatis与spring的整合

    一.整合需要 1.1.方法 上一章中的数据 需要spring通过单例方式管理SqlSessionFactory spring和mybatis整合生成代理对象,使用SqlSessionFactory创建 ...

  9. UIView与CALayer的区别

    1.UIView相比CALayer最大区别是UIView可以响应用户事件,而CALayer不可以.UIView侧重于对显示内容的管理,CALayer侧重于对内容的绘制. 2.UIView和CALaye ...

  10. Retrofit源码设计模式解析(下)

    本文将接着<Retrofit源码设计模式解析(上)>,继续分享以下设计模式在Retrofit中的应用: 适配器模式 策略模式 观察者模式 单例模式 原型模式 享元模式 一.适配器模式 在上 ...