题目传送门
题目
欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?
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
思路:
即首先判断能否构成环,接着判断是否图中所有的点的度都为偶数,同时满足这两点,才能构成欧拉回路。
dfs法
#include <iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define maxn 2000
using namespace std;
int degree[maxn],n,m;
bool visit[maxn];
vector<int>edge[maxn];
void dfs(int point){
int i,j,p;
visit[point]=1;
for(i=0;i<edge[point].size();i++){
p = edge[point][i];
if(!visit[p])
dfs(p);
}
}
int main() {
int i,j,a,b;
while(scanf("%d",&n)!=EOF&&n){
scanf("%d",&m);
for(i=1;i<=n;i++){ //初始化
degree[i]=0;
edge[i].clear();
}
for(i=0;i<m;i++){
scanf("%d%d",&a,&b);
if(a!=b){ //无向图
edge[a].push_back(b);
edge[b].push_back(a);
degree[a]++;
degree[b]++;
}
}
bool flag=0;
for(i=1;i<=n;i++){
if(degree[i]&1){
printf("0\n");
flag=1;
break;
}
}
if(flag)
continue;
memset(visit,0,sizeof(visit));
dfs(1); //判断是否连通
for(i=1;i<=n;i++){
if(!visit[i]){
flag=1;
break;
}
}
if(flag)
printf("0\n");
else
printf("1\n");
}
return 0;
}
并查集法
#include<cstdio>
using namespace std;
const int N = 1e3+5;
int deg[N];
int uf[N];
int find1(int x)
{
int r = x;
while (r!=uf[r]) r=uf[r];
for (int i=x,j;i!=r;i=j){
j = uf[i];
uf[i] = r;
}
return r;
}
void join(int a,int b)
{
int c = find1(a),d = find1(b);
if (c!=d) uf[c] = d;
}//并查集找组织
int main()
{
int T,n,m,u,v;
while (scanf("%d",&n),n){
scanf("%d",&m);
for (int i=1;i<=n;i++) deg[i] = 0,uf[i] = i;///初始化
while (m--){
scanf("%d %d",&u,&v);
join(u,v);
deg[u]++;
deg[v]++;
}
int cnt = 0;
for (int i=1;i<=n;i++) if (uf[i]==i) cnt++;
if (cnt==1){
bool flag = true;
for (int i=1;i<=n;i++) if (deg[i]&1) {flag = false;break;}/*奇数&1=真,偶数&1=假。无向图中只有每个点的度都为偶数,才是欧拉回路*/
if (flag) printf("1\n");
else printf("0\n");
}
else printf("0\n");
}
return 0;
}
版权声明:本文为qq_44587145原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。