欧拉环:图中经过每条边一次且仅一次的环;
欧拉路径:图中经过每条边一次且仅一次的路径;
欧拉图:有至少一个欧拉环的图;
半欧拉图:没有欧拉环,但有至少一条欧拉路径的图。
欧拉路径和欧拉图的具体判断可 参考此处
要特别注意的是,不要把欧拉路径和哈密顿路径搞混淆了,欧拉路径是每条边只经过一次的路径(而一个点可以经过多次),哈密顿路径是每个点只能经过一次的路径。哈密顿路径问题比欧拉路径问题要难的多。
不管是有向图还是无向图,欧拉回路都具有一个很明显的性质:对每个点有多少条边进去就一定要有多少条边出来。如果是欧拉路径,那么可以允许在路径的首位两端有少一个进去/出来的。
利用这个性质有以下算法求欧拉路径
即:选好起点后,把每走过的边在原图中删除。
如何选起点:1)如果所有的点都是入度==出度,任意起点都可以;2)否则,无向图:选其中一个度数为奇数的点;有向图:选出度比入度大1的点。
伪代码如下:
DFS(u): While (u存在未被删除的边e(u,v)) 删除边e(u,v) DFS(v) End PathSize ← PathSize + 1 Path[ PathSize ] ← u
POJ2337,有向图的欧拉路径。
关键在于如何建图,并且要求字典序输出答案。
【代码&&模版】
/* ***********************************************
Author :angon
************************************************ */
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <stack>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
#define showtime fprintf(stderr,"time = %.15f\n",clock() / (double)CLOCKS_PER_SEC)
#define lld %I64d
#define REP(i,k,n) for(int i=k;i<n;i++)
#define REPP(i,k,n) for(int i=k;i<=n;i++)
#define scan(d) scanf("%d",&d)
#define scanl(d) scanf("%I64d",&d)
#define scann(n,m) scanf("%d%d",&n,&m)
#define scannl(n,m) scanf("%I64d%I64d",&n,&m)
#define mst(a,k) memset(a,k,sizeof(a))
#define LL long long
#define N 1005
#define mod 1000000007
inline int read(){int s=0;char ch=getchar();for(; ch<'0'||ch>'9'; ch=getchar());for(; ch>='0'&&ch<='9'; ch=getchar())s=s*10+ch-'0';return s;}
string s[N];
int out[26],in[26],vis[2005];
struct Edge
{
int to,next;
int idx;
}edge[2100];
int head[30],tot=0;
int num,path[N];
void addedge(int u,int v,int idx)
{
edge[tot].to = v;
edge[tot].next = head[u];
edge[tot].idx = idx;
head[u] = tot++;
}
void dfs(int u)
{
for(int i =head[u]; ~i; i=edge[i].next)
{
if(vis[i]) continue;
vis[i] = 1;
dfs(edge[i].to);
path[num++] = edge[i].idx;
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int t; scan(t);
while(t--)
{
int n; scan(n);
REP(i,0,n)
cin>>s[i];
sort(s,s+n);
mst(head,-1); tot=0;
mst(out,0); mst(in,0); mst(vis,0);
int start = 100;
for(int i=n-1;i>=0;i--)
{
int u = s[i][0] - 'a';
int v = s[i][s[i].length() - 1]- 'a';
addedge(u,v,i);
out[u]++;
in[v]++;
start = min(min(u,v),start);
}
bool flag = 0;
int c1 = 0, c2 = 0;
for(int i=0;i<26;i++)
{
if(out[i] - in[i] > 1 || in[i] - out[i] > 1)
{
flag = 1;
break;
}
if(out[i] - in[i] == 1)
c1++,start = i;
if(out[i] - in[i] == -1)
c2++;
}
if(flag || (c1+c2!=0 && c1+c2!=2))
{
puts("***");
continue;
}
num = 0;
dfs(start);
if(num != n)
{
puts("***");
continue;
}
for(int i=num-1;i>=0;i--)
{
cout<<s[path[i]];
printf("%c",i==0?'\n':'.');
}
}
return 0;
}

535

被折叠的 条评论
为什么被折叠?



