您的位置:首页 > 其它

欧拉路 小结(POJ 2337 为例子)

2015-06-05 11:47 267 查看
最近把拓扑排序和欧拉路看了一遍,前面已经说了拓扑排序,今天就来说说一下,欧拉路。

从POJ 2337 这道题开始说吧。

这道的题目的意思是给你一些单词,问你可不可以首尾连接起来。

思路:判断是不是连通图+欧拉图判断+输出欧拉路路径(字典序最小的)

先来说下是不是连通图,要用到并查集(自己复习了一下, 就明了)

简单说下,就是把一个节点的上司给另一个节点,省去中间的领导

直接看他隶属哪个最大的头目。然后再看看是不是所有人的老大是不是一个人~。

欧拉路的判断:

无向欧拉图:所有节点的度数(出度+入度)都是偶数

或者只有两个点的度数为奇数,这两个点是起点和中点

有向欧拉图:所有点的入度=出度

或者只有一点的入度=出度+1(这是起点)和只有一点的出度=入度+1(这点是起点)

然后是路径输出,用到DFS,用到的是图论中的路径连接那块的知识。

类似于向前星。

代码可能比较多,但是以简单的想法慢慢写的,好理解。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1000001;
int p[maxn];
int c1[maxn*3],c2[30],cnt1,cnt2,cnt;
int cnt_in[maxn],cnt_out[maxn],kk[maxn];
int n;
int kaitou;//第一个dfs的开头
struct P
{
int st,ed;
bool del;
}edge[maxn];
int vis[maxn];
struct node
{
char s[21];
bool operator<(const node &C)const
{
return strcmp(s,C.s)<0;
}
} str[maxn];
int cmp(char *s1,char *s2)
{
return strcmp(s1,s2)<0;
}
int cha(int x)
{
return x==p[x]?x:cha(p[x]);
}
void bing(int x,int y)
{
x=cha(x);
y=cha(y);
if(x!=y)
p[x]=y;
}
int chahao(int x)
{
for(int i=0; i<cnt2; i++)
if(c2[i]==x)
return 1+i;
}
int panduan1()
{
memset(cnt_in,0,sizeof(cnt_in));
memset(cnt_out,0,sizeof(cnt_out));
for(int i=1; i<=cnt2; i++)
p[i]=i;
for(int i=0; i<n; i++)
{
int len=strlen(str[i].s);
int x=str[i].s[0]-'a'+1;
int y=str[i].s[len-1]-'a'+1;
x=chahao(x);
y=chahao(y);
cnt_out[x]++;
cnt_in[y]++;
//  AddEdge(i,y);
edge[i].st=x;
edge[i].ed=y;
edge[i].del=false;
bing(x,y);
}
int sum=0;
for(int i=1; i<=cnt2; i++)
if(i==p[i])
sum++;
if(sum>1)
return 0;
return 1;
}
int panduan2()
{
int f1=0,f2=0,sum=0;
int t;
// for(int i=1;i<=cnt2;i++)
// printf("%d %d\n",cnt_in[i],cnt_out[i]);
for(int i=1; i<=cnt2; i++)
{
if(cnt_in[i]==cnt_out[i])
sum++;
if(cnt_in[i]==cnt_out[i]+1)
f1++;
if(cnt_out[i]==cnt_in[i]+1)
{
t=i;
f2++;
}
}
//  printf("%d %d %d\n",sum,f1,f2);
kaitou=edge[0].st;
if(cnt2==1)
return 1;
if(f1==1&&f2==1)
{
kaitou=t;
return 1;
}
if(sum==cnt2)
return 1;
return 0;
}
void dfs(int u)
{

for ( int i = 0; i < n ;i++ )
{
if ( ! edge[i].del && edge[i].st == u )
{
edge[i].del = true;
dfs ( edge[i].ed );
kk[cnt++] = i;
}
}
}
void dfs_out()
{
memset(vis,0,sizeof(vis));

dfs(kaitou);
printf("%s",str[kk[cnt-1]].s);
for(int i=cnt-2;i>=0;i--)
printf(".%s",str[kk[i]].s);
puts("");
}

int main()
{
int tt;
scanf("%d",&tt);
while(tt--)
{

scanf("%d",&n);
cnt=0;
for(int i=0; i<n; i++)
scanf("%s",str[i].s);
sort(str,str+n);
// for(int i=0;i<n;i++)
//printf("%s ",str[i].s);
cnt1=0,cnt2=1;
for(int i=0; i<n; i++)
{
int len=strlen(str[i].s);
int x=str[i].s[0]-'a'+1;
int y=str[i].s[len-1]-'a'+1;
c1[cnt1++]=x;
c1[cnt1++]=y;
}
//for(int i=0;i<cnt1;i++)
// printf("%d ",c1[i]); puts("");
sort(c1,c1+cnt1);
c2[0]=c1[0];
for(int i=1; i<cnt1; i++)
{
if(c1[i]!=c1[i-1])
c2[cnt2++]=c1[i];
}
//保存不同的字母
//  for(int i=0;i<cnt2;i++)
// printf("%d ",c2[i]);
if(panduan1()==0)//判断是不是连通图
{
// puts("11111");
puts("***");
}
else
{
if(panduan2()==0)//判断是不是欧拉图,即一笔画
{
puts("***");
}
else
{
dfs_out();
}
}

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: