欧拉回路
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 13320 Accepted Submission(s): 4972
Problem Description
欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?
Input
测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是节点数N ( 1 < N < 1000 )和边数M;随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个节点的编号(节点从1到N编号)。当N为0时输入结
束。
束。
Output
每个测试用例的输出占一行,若欧拉回路存在则输出1,否则输出0。
Sample Input
3 3 1 2 1 3 2 3 3 2 1 2 2 3 0
Sample Output
1 0
Author
ZJU
Source
假设5 个顶点,10条边
起始顶点 1 2 3 4 5
起始父节点 1 2 3 4 5
1---2
1---3
1---4
1---5
2---3
2---4
3---5
4---5
1.并查集
若为欧拉图,相当于图中所有顶点都相连(类比最小生成树),所以除了根节点以外,每个顶点都指向其他顶点(最终都指向跟节点)
欧拉图顶点 1 2 3 4 5
父节点 2(!1) 3(!2) 4(!3) 5(!4) 5
这里假设顶点6是根节点
判断一个图是否为欧拉回路充要条件是 判断图中所有顶点的度是否都为偶数,还需判断是否为联通图。 判断联通图方法为并查集,这里使用最简单的并查集
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
using namespace std;
#define INF 0x3f3f3f3f
const int MaxV = 1005;
int degree[MaxV],fa[MaxV];//分别表示顶点的度数和顶点的父节点,就是指向该点的顶点
int N,M;
int find(int x)//获取根节点
{
return fa[x]==x?x:find(fa[x]);
}
int main(){
while(scanf("%d",&N)){
if(N==0)break;
scanf("%d",&M);
memset(degree,0,sizeof(degree));//初始所有节点的度为0
for(int i = 1 ; i <= N; i++)
fa[i] = i ; //所有结点的父节点都是自身
for(int i = 0 ; i < M ; i ++){
int u,v;
scanf("%d%d",&u,&v);
degree[u]++; //无向图,出度+1
degree[v]++; //入度+1
int x = find(fa[u]);
int y = find(fa[v]);
if(x!=y) //判断输入的两个顶点是否属于同一个树,即是否联通
fa[x]=y; //如果不联通,将其联通
}
bool t1=false,t2=true ;
int cnt = 0 ;
for(int i = 1 ; i <= N ; i++){
if(fa[i] == i ) //判断所有顶点是否联通,若联通说明每个顶点的父节点都为某个顶点
cnt++; //也就是说所有顶点中只有一个顶点与父节点相同
if(degree[i]&1){ //判断每个顶点的度数是否为奇数,一旦是,则证明不是欧拉图
t2 = false ;
break;
}
}
if (cnt == 1)
t1= true;
if(t1 && t2 )printf("1\n");//两个条件同时成立说明为欧拉图
else printf("0\n");
}
return 0;
}
2 .dfs
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cstdlib>
#include<vector>
#include<cstdio>
using namespace std;
#define INF 0x3f3f3f3f
const int MaxV = 1005;
int vis[MaxV];
vector<int>vec[MaxV];
int N,M;
void dfs(int i ){
vis[i] = 1;
vector<int>::iterator it;
for(it = vec[i].begin() ; it!=vec[i].end(); it++){
if(vis[*it] == 0)
dfs(*it);
}
}
int main(){
while(scanf("%d",&N)){
if(N==0)break;
scanf("%d",&M);
memset(vis,0,sizeof(vis));
for(int i = 1 ; i <= N; i++)
vec[i].clear();
for(int i = 0 ; i < M ; i ++){
int u,v;
scanf("%d%d",&u,&v);
vec[u].push_back(v);
vec[v].push_back(u);
}
dfs(1);
int cnt = 0 ;
bool t1 = false ,t2 = true;
for(int i = 1 ; i <= N ; i++){
if(!vis[i])
cnt++;
if(vec[i].size()&1){
t2 = false ;
}
}
if (!cnt)
t1= true;
if(t1 && t2 )printf("1\n");//两个条件同时成立说明为欧拉图
else printf("0\n");
}
return 0;
}