您的位置:首页 > 其它

欧拉回路两题 uva 10129 + uva 10054

2014-01-31 21:43 309 查看
欧拉回路:图G的一个回路,若它恰通过G中每条边一次,则称该回路为欧拉(Euler)回路。
具有欧拉回路的图称为欧拉图(简称E图)。
现在把最近做的两道欧拉回路的题一起贴了,思路方法都类似。

uva 10129 Play On Words

链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=13&page=show_problem&problem=1070

题意是给你若干个单词看能不能组成一个链,前一个单词的最后一个字母和后一个单词的第一个字母相同。

刚开始时候只看样例来着以为是从第一个开始向后判,能不能一次连上,题意完全理解错了。

把首字母和末字母看成点,单词看成线的有向图。

两部分。

第一部分判连通。(DFS或并查集)

第二部分所有点入度等于出度,或者存在一个起点(出度比入度大一)一个终点(入度比出度大一)。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<ctype.h>
#include<algorithm>
#include<string>
#define PI acos(-1.0)
#define maxn 160
#define INF 1<<25
#define MAX 0x7fffffff
typedef long long ll;
using namespace std;
int vv[30];
int M[30][30];
int rec2;
int dfs(int x)
{
rec2++;
vv[x]=1;
for(int i=0; i<26; i++)
{
if(!    vv[i]&&M[x][i])
dfs(i);
}
}
int main()
{
char ss[1005];
int in[30];
int ou[30];
int tot;
scanf("%d",&tot);
char c;
for(int ii=0; ii<tot; ii++)
{
int tt;
scanf("%d",&tt);
int jud=0;
memset(in,0,sizeof(in));
memset(ou,0,sizeof(ou));
memset(vv,0,sizeof(vv));
memset(M,0,sizeof(M));
for(int i=0; i<tt; i++)
{
scanf("%s",ss);
int len=strlen(ss);
ou[ss[0]-'a']++;
in[ss[len-1]-'a']++;
M[ss[0]-'a'][ss[len-1]-'a']=1;
}
if(tt==1)
{
printf("Ordering is possible.\n");
continue;
}
int st=-1,en=-1;
int rec=0;
for(int i=0; i<26; i++)
{
if(ou[i]-in[i]==1&&st==-1)
st=i;
else if(ou[i]!=in[i])
jud=1;
if(in[i]||ou[i])
rec++;
}
if((st==-1&&en!=-1)||(st!=-1&&en==-1))
jud=1;
rec2=0;
if(!jud)
if(st!=-1)
dfs(st);
else if(st==-1)
for(int i=0; i<26; i++)
if(ou[i]!=0)
{
dfs(i);
break;
}
if(rec!=rec2)
jud=1;
if(jud)
printf("The door cannot be opened.\n");
else printf("Ordering is possible.\n");
}
}
uva 10054 The Necklace

链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=12&page=show_problem&problem=995

题意是给若干个项链珠子,每科珠子上面有两种颜色。要求你判断出能不能组成一个完整的相邻的珠子的相邻颜色相同的项链。

与上题不同的是这道题给的不是有向图,是一个无向图。也是判连同和出入度两部分,这道题所有点的出度必须等于入度,因为项链不存在起点终点。还要求输出遍历结果,从白皮书上的代码学习的,挺容易理解的。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<ctype.h>
#include<algorithm>
#include<string>
#define PI acos(-1.0)
#define maxn 160
#define INF 1<<25
#define MAX 0x7fffffff
typedef long long ll;
using namespace std;
int tot,tt,jud;
int in[55];
int vv[55][55],M;
int top,bb[1005][2];
int num[55];
int init()
{
for(int i=0; i<=50; i++)
{
num[i]=i;
}
}
int findset(int x)
{
if(x==num[x])
return x;
return num[x]=findset(num[x]);
}
int unionset(int x,int y)
{
int xx=findset(x);
int yy=findset(y);
if(xx==yy)
return 0;
else if(xx<yy)
num[yy]=xx;
else num[xx]=yy;
}
int euler(int u)
{
for(int v=0; v<=M; v++)
{
if(vv[u][v])
{
vv[u][v]--;
vv[v][u]--;
euler(v);
printf("%d %d\n",v,u);
}
}
}
int main()
{
scanf("%d",&tot);
for(int ii=1; ii<=tot; ii++)
{
jud=1;
top=0;
memset(vv,0,sizeof(vv));
memset(in,0,sizeof(in));
scanf("%d",&tt);
M=0;
init();
for(int i=0; i<tt; i++)
{
int x,y;
scanf("%d%d",&x,&y);
vv[x][y]++;
vv[y][x]++;
in[x]++;
in[y]++;
unionset(x,y);
if(x>M)
M=x;
if(y>M)
M=y;
}
printf("Case #%d\n",ii);
for(int i=0; i<=M; i++)
{
if(findset(i)==i)
continue;
for(int j=0; j<=M; j++)
{
if(findset(j)==j)
continue;
if(findset(i)!=findset(j))
jud=0;
}
}
for(int i=0; i<=M; i++)
{
if(in[i]%2!=0)
jud=0;
}
if(jud)
euler(M);
if(!jud)
printf("some beads may be lost\n");
if(ii!=tot)
printf("\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息