通过有向图或者无向图中所有边且每边只通过一次的路称为欧拉通路,相应的回路称为欧拉回路,具有欧拉回路的图称为欧拉图,具有欧拉通路的图称为半欧拉图
(注意,只能大1,而且这样的点分别只能有1个,而且存在起点就一定要存在终点,存在终点就一定要存在起点)
一个图如何使欧拉图呢,首先判断它要是连通的
判断有向图是否存在欧拉路径(poj1386)
题意:给你n个单词,要求这些单词相连,要求是前面的字母的尾字母和后面单词的头字母相同,问你这n个单词能不能全部连起来,可以连成一条链或者连成一个环
另外单词只有小写字母。很容易想到,顶点集合就是26个小写字母,用1到26来表示,一个单词的首字母和尾字母就是一条有向边,注意是有向边,因为单词是不能倒回来的
其实就是问你这个图是否存在欧拉道路(一条链的情况)或者欧拉回路(环的情况),反正存在欧拉路就是成功的,否则就是失败
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int chu[30],ru[30],wuxiang[30][30],via[30];
void cha(int i)
{
for(int j=1;j<=26;j++)
{
if(wuxiang[i][j]==1&&via[j]==0)
{
via[j]=1;
cha(j);
}
}
}
int liantong()
{
// printf("@\n");
for(int i=1;i<=26;i++)
{
if(ru[i]!=0||chu[i]!=0)
{
cha(i);
break;
}
}
for(int i=1;i<=26;i++)
{
if(ru[i]!=0||chu[i]!=0)
{
if(via[i]==0)
return 0;
}
}
return 1;
}
int oula()
{
//printf("!\n");
int r=0,c=0,i;
for(i=1;i<=26;i++)
{
if(ru[i]!=0||chu[i]!=0)
{
if(ru[i]-chu[i]==1)
{
r++;
if(r>1)
break;
}
else if(chu[i]-ru[i]==1)
{
c++;
if(c>1)
break;
}
else if(chu[i]-ru[i]>1||ru[i]-chu[i]>1)
break;
}
}
if(i<=26)
return 0;
// printf("-\n");
return 1;
}
int main()
{
int T,n,a,b;
char s[1005];
int str;
scanf("%d",&T);
for(int j=0;j<T;j++)
{
memset(via,0,sizeof(via));
memset(chu,0,sizeof(chu));
memset(ru,0,sizeof(ru));
memset(wuxiang,0,sizeof(wuxiang));
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",s);
str=strlen(s);
a=s[0]-'a'+1;
b=s[str-1]-'a'+1;
chu[a]++;
ru[b]++;
wuxiang[a][b]=wuxiang[b][a]=1;
}
if(liantong()&&oula())
{
// printf("|\n");
printf("Ordering is possible.\n");
}
else
printf("The door cannot be opened.\n");
}
return 0;
}
看到有人用DFS判断是否连通
下面说一个进化版,poj1300,Door man,有N个房间,每个房间有几个门,给出一个人目前的房间号M,然后判断他能不能路过每一个门,每个门只能过一次,最后回到0点。要达成这样的结果又两种方式,第一种起点在零点,每个房间有偶数个门,第二种只有起点和0点不是偶数
这道题有sscan的用法
//
// main.cpp
// B.p1300
//
// Created by Mr.Xue on 17/2/9.
// Copyright © 2017年 Mr.Xue. All rights reserved.
//
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
int readline(char *s)
{
int L;
for(L=0;(s[L]=getchar())!='\n'&&s[L]!=EOF;L++);
s[L]=0;
return L;
}
int main()
{
int i,j,M,N,doors;
char buf[500];
int door[21];
while(!readline(buf))
{
if(buf[0]=='S')
{
memset(door,0,sizeof(door));
sscanf(buf,"%*s %d %d",&M,&N);
doors=0;
for(i=0;i<N;i++)
{
readline(buf);
int k=0;
while(sscanf(buf+k,"%d",&j)==1)
{
while(buf[k]&&buf[k]==' ')
k++;
door[i]++;
door[j]++;
doors++;
}
}
readline(buf);
int ji=0;
for(i=0;i<N;i++)
{
if(door[i]%2!=0)
ji++;
}
if(M==0&&ji==0)
printf("Yes%d\n",doors);
else if(ji==2&&door[0]%2!=0&&door[M]%2!=0&&M!=0)
printf("Yes%d\n",doors);
else
printf("N0\n");
}
else if( !strcmp(buf, "ENDOFINPUT") )
break;
}
//cout << "Hello, World!\n";
return 0;
}