首页 > 试题广场 >

欧拉回路

[编程题]欧拉回路
  • 热度指数:6291 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
    欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?

输入描述:
    测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是节点数N ( 1 < N < 1000 )和边数M;随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个节点的编号(节点从1到N编号)。当N为0时输入结束。


输出描述:
    每个测试用例的输出占一行,若欧拉回路存在则输出1,否则输出0。
示例1

输入

3 3
1 2
1 3
2 3
3 2
1 2
2 3
0

输出

1
0
/*
*直接判断各个点的度数是不是偶数,默认是连通的??🤣🤣 */

#include<bits/stdc++.h>

using namespace std;

const int maxn = 1e3;
int du[maxn+5];
int n, m;

bool isAllEven()
{
    for(int i = 1;i <= n; i++)
    {
        if(du[i] & 1) return false;
    }
    return true;
}

int main()
{
    ios::sync_with_stdio(false);
    int u, v;
    while(cin >> n >> m)
    {
        fill(du+1, du+n+1, 0);
        for(int i = 1;i <= m; i++)
        {
            cin >> u >> v;
            du[u]++; du[v]++;
        }
        cout << isAllEven() << "\n";
    }
    return 0;
}

编辑于 2021-01-20 19:06:09 回复(0)
考虑欧拉回路的性质。
所有度应该均为偶度。非孤立顶点应该连通。连通用并查集做。
需要注意的是,孤立顶点的情况。
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <queue>
#include <math.h>
#include <cmath>
#include <string>
#include <sstream>
#include <set>
#define INF 0x3f3f3f3f
#pragma warning(disable:4996)
using namespace std;

typedef struct {
	int father;
	int height;
}juNode;

vector<juNode> juSet;

int find_set(int x) {
	while (x != juSet[x].father)
		x = juSet[x].father;
	return x;
}

void Union(int a, int b) {
	int fatherX, fatherY;
	fatherX = find_set(a);
	fatherY = find_set(b);
	if (fatherX != fatherY) {
		if (juSet[fatherX].height > juSet[fatherY].height) {
			juSet[b].father = fatherX;
			//所有以fatherY为头的都要修改到fatherX身上
			for (int i = 1; i < juSet.size();i++) {
				if (juSet[i].father == fatherY) {
					juSet[i].father = fatherX;
				}
			}
		}
		else {
			if (juSet[fatherX].height == juSet[fatherY].height) {
				juSet[fatherY].height++;
			}
			juSet[a].father = fatherY;
			for (int i = 1; i < juSet.size();i++) {
				if (juSet[i].father == fatherX) {
					juSet[i].father = fatherY;
				}
			}
		}
	}
}

int judge(vector<int> node){
	for (int i = 1; i < node.size();i++) {
		if (node[i] % 2 != 0)
			return 0;
	}
	int count = 0;
	for (int i = 1; i < juSet.size(); i++) {
		if (juSet[i].father == i && node[i]!=0)
			count++;
	}
	if (count >= 2)
		return 0;
	else
		return 1;
}

int main()
{
	int n, m;
	while (scanf("%d", &n) != EOF && n!=0) {
		cin >> m;
		juNode TempJu;
		for (int i = 0; i <= n; i++) {
			TempJu.father = i;
			TempJu.height = 0;
			juSet.push_back(TempJu);
		}
		vector<int> node(n + 1 , 0);
		int a, b;
		for (int i = 0; i < m; i++) {
			cin >> a >> b;
			node[a]++; node[b]++;
			Union(a, b);
		}
		if (judge(node))
			cout << "1" << endl;
		else
			cout << "0" << endl;
	}
}



发表于 2019-09-10 15:34:46 回复(0)

判断各个节点的度是否为偶数,自环增加度为2,不影响,所以可以加上去

while True:
    try:
        n,m = list(map(int, input().split()))
        if n == 0:
            break
        nodes = [0 for i in range(n+1)]
        for i in range(m):
            temp = list(map(int, input().split()))
            nodes[temp[0]] += 1
            nodes[temp[1]] += 1
        whetherEuler = True
        for i in range(1,n+1):
            if nodes[i] % 2 == 1:
                whetherEuler = False
                break
        if whetherEuler:
            print(1)
        else:
            print(0)
    except Exception:
        break
编辑于 2018-09-28 16:36:25 回复(0)
这道题目要注意如果图中存在孤立起点,那么在考虑图的连通性时,不需要考虑该节点
#include <stdio.h>
#include <string.h>

#define MAX 1010

int degree[MAX];
int father[MAX];

int find(int x)
{
    if(father[x]==x) return x;
    else
    {
        int tmp=find(father[x]);
        father[x]=tmp;
        return tmp;
    }
}

int main()
{
    int N,M;
    int a,b;
    int i;
    while(scanf("%d",&N)!=EOF&&N)
    {
        scanf("%d",&M);
        int flag=1;
        memset(degree,0,sizeof(degree));
        for(i=1;i<=N;i++)
        {
            father[i]=i;
        }
        int temp=0;
        for(i=0;i<M;i++)
        {
            scanf("%d %d",&a,&b);
            degree[a]++;
            degree[b]++;
            temp=a;
            a=find(a);
            b=find(b);
            if(a!=b)
            {
                father[a]=b;
            }
        }
        for(i=1;i<=N;i++)
        {
            if(degree[i]%2==1)
            {
                flag=0;
                break;
            }
        }
        if(temp==0||flag==0) //先保证所有结点的度数都为偶数,并且图中至少存在边
        {
            printf("0\n");
            continue;
        }
        int root=0;
        for(i=1;i<=N;i++) //再判断图是否存在且仅存在一个连通子图(不计孤立点)
        {
            if(father[i]==i&&degree[i]) root++;
        }
        if(root==1) printf("1\n");
        else printf("0\n");
    }
}

发表于 2018-08-19 10:40:17 回复(0)
/*也真是呵呵了。针对无向图欧拉回路的各种判别不一,我认为相对正确的一种说法是下面这种:
无向图存在欧拉回路的充要条件
一个无向图存在欧拉回路,当且仅当该图所有顶点度数都为偶数,且该图是连通图。 为什么呵呵:这道题AC的代码也是醉了,直接判断所有顶点的度数是否都为偶数即可, 无需判断是否连通。但正常逻辑应该是先判别整个图是否连通(使用并查集), 再判别是否所有顶点度数位偶数。 代码如下,简单的mmp*/ import java.util.Scanner; public class Main {     public static void main(String[] args) {         Scanner scanner = new Scanner(System.in);         while (scanner.hasNext()) {             int N = scanner.nextInt();             if (N == 0)                 break;             int M = scanner.nextInt();             int[] branch = new int[N + 1];             for (int i = 0; i < M; i++) {                 int a = scanner.nextInt();                 int b = scanner.nextInt();                 branch[a]++;                 branch[b]++;             }             int i = 0;             for (i = 0; i < branch.length; i++)                 if (branch[i] % 2 == 1)                     break;             if (i < branch.length)                 System.out.println(0);             else                 System.out.println(1);         }         scanner.close();     } }

编辑于 2018-02-07 22:28:42 回复(10)
确定无向图欧拉回路的充要条件:除孤立节点外,其它节点满足 1.连通 2.度为偶数

#include <cstdio>
#include <algorithm>
 
using namespace std;
 
int father[1001];
//并查集找父亲的操作
int findFather(int x){
    while(x!=father[x]){
        x = father[x];
    }
    return x;
}
//并查集合并的操作
void Union(int a, int b){
    int af = findFather(a);
    int bf = findFather(b);
    father[bf] = af;
}
 
int main(){
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        int d[1001]; //节点度
        fill(d,d+1001,0);
        for(int i=0;i<=n;i++) father[i]=i; //初始化father数组
        for(int i=0;i<m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            d[a]++;
            d[b]++;
            Union(a,b);
        }
        int tmp=0;
        for(int i=1;i<=n;i++){
            //有奇数度,应打印0
            if(d[i]%2!=0){
                tmp++;
                break;
            }
        }
        if(tmp>0){
            printf("0\n");
            continue;
        }
        int t = 1;
        for(int i=0;i<=n;i++){  //寻找一个非孤立节点,存入t
            if(d[i]!=0){
                t = i;
                break;
            }
        }
        int f = findFather(t);
        bool flag = false;
        for(int i=2;i<=n;i++){
            //既不是孤立节点,也不连通,应打印0
            if(findFather(i)!=f && findFather(i)!=i){
                flag = true;
                break;
            }
        }
        if(flag){
            printf("0\n");
            continue;
        }
        if(n!=0){
            printf("1\n");
        }
         
    }
    return 0;
}

编辑于 2018-03-15 10:52:51 回复(13)
#include<stdio.h>
int fa[10005],cnt[10005];
int find(int x){
	return fa[x]==x?x:fa[x]=find(fa[x]);
}
int main(){
	int n,m,x,y,i;
	//freopen("input.txt","r",stdin);
	while(scanf("%d",&n)!=EOF&&n){
		scanf("%d",&m);
		for(i=0;i<10005;i++) fa[i]=i,cnt[i]=0;
		while(m--){
			scanf("%d%d",&x,&y);
			int fax=find(x),fay=find(y);
			if(fax-fay) fa[fax]=fay;
			cnt[x]++,cnt[y]++;
		}
		int f=find(1),flag=1;
		if(cnt[1]%2) flag=0;
		for(i=2;i<=n;i++)
			if((cnt[i]&&find(i)!=f)||cnt[i]%2){
				flag=0;
				break;
			}
		printf("%d\n",flag);
	}
}

发表于 2017-09-12 18:52:01 回复(0)
/*
    欧拉回路:首先对于无向图而言,欧拉回路指的是通过所有的边有且仅有一次,然后可以回到原点的图
    需要满足两个要求:
    ①图是连通图=》采用并查集进行判断
    ②图中所有顶点的度数(入度+出度)均为偶数=》采用inDegree数组进行标记
    注意点:孤立点忽略不计(只存在单点回路的边,不不存在任何相连的边)

    需要注意一下用例:
    用例:
    7 8
    2 6
    5 4
    6 6
    2 1
    2 2
    5 6
    1 4
    5 5

    对应输出应该为:

    1

    你的输出为:

    0

    该例中很明显结点3,7是孤立的结点,但欧拉图只要求通过所有的边,然后能回到原点即可,
    因此对于孤立的点可以无需考虑,这里采用set存储非孤立的结点的编号。后续统计度数的
    奇偶性以及连通分量的个数时可以忽略这些孤立的顶点不管。
*/
#include <iostream>
#include <set>
#define N 1001
using namespace std;
int Tree[N];

int inDegree[N];
set<int> Mapping;

int findRoot(int x){
    if(Tree[x]==-1)return x;
    else{
        Tree[x]=findRoot(Tree[x]);
        return Tree[x];
    }
}

int main()
{
    int n,m;
    int a,b;
    while(~scanf("%d",&n)){
        if(n==0)break;
        scanf("%d",&m);
        for(int i=1;i<=n;i++){
            Tree[i]=-1;
            inDegree[i]=0;
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d",&a,&b);
            if(a==b)continue;//单点回路忽略不计
            Mapping.insert(a);
            Mapping.insert(b);
            inDegree[a]++;
            inDegree[b]++;
            a = findRoot(a);
            b = findRoot(b);
            if(a!=b)Tree[a]=b;
        }
        int cnt=0;//统计连通分量的个数
        for(auto it=Mapping.begin();it!=Mapping.end();it++){
            if(Tree[*it]==-1)cnt++;
        }
        if(cnt!=1){
            printf("0\n");
        }
        else{
            int cnt1=0;//统计度数为奇数的结点个数
            for(auto it=Mapping.begin();it!=Mapping.end();it++){
                if(inDegree[*it]&1==1){
                    cnt1++;
                }
            }
            if(cnt1==0){
                printf("1\n");
            }
            else{
                printf("0\n");
            }
        }
    }
    return 0;
}
/*
3 3
1 2
1 3
2 3
3 2
1 2
2 3
0
*/

编辑于 2019-03-15 11:40:21 回复(0)
正规来说,欧拉回路满足条件应该是 连通图,且每个点的度为偶数,但是这道题的数据只判断度就可以了,我被卡了最后5%,发现是自环我给算了度数,如果不算的话就通过了,所以这题没通过的同学可以看下是不是算了自环
贴一下带连通图检测的(DFS)的代码 
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#define mem(a,b) memset(a,b,sizeof(a))
#define M 202
using namespace std;
typedef long long ll;
struct stack
{
    int top,node[M];
}s;
int e[M][M],n;
int icount = 0;
int visited[1000];
void DFS(int i)
{
    int j = 0;
    visited[i] = 1;
    icount++;
    for(j=0; j<n; j++)
    {
        if(e[i][j]==1 && !visited[j])//i和j有关系相邻,并且j顶点没有被访问过
        {
            DFS(j);
        }
    }
}
bool judge(){                //判断是否所有点已被遍历过
    for(int i=1;i<=n;++i)
        if(!visited[i])
            return false;
    return true;
}

int main( )
{
    int i,j,u,v,m,degree,num=0,start=0;
    scanf("%d%d",&n,&m);
    mem(e,0);
    for(i=0;i<m;i++)
    {
        scanf("%d%d",&u,&v);
        e[u-1][v-1]=e[v-1][u-1]=1;
    }
    for(i=0;i<n;i++)
    {
        degree=0;
        for(j=0;j<n;j++)
        if(i!=j){//这的测试数据自环不能算度
            degree+=e[i][j];
        }

        if(degree&1)
        {
            start=i;
            num++;
        }
    }
    //cout<<"num "<<num<<endl;
    if((num==0)&&n<m){
          //牛客的判题数据不需要检查是不是连通图,
        //DFS(0);
        printf("%d",1);
       // if(judge())
        //    printf("%d",1);
       // else
       //     printf("%d",0);
    }

    else printf("%d",0);
    return 0;
}


发表于 2018-06-02 21:18:03 回复(1)
//无向图判断是否有欧拉回路
//1. 联通;2. 度为0
//但是这个题还有坑的一点,就是有孤立点。按照题意度为0的孤立点对结果没有影响,但是有自环孤立点则不是欧拉图(无法一笔画)
#include <iostream>
#include<stdio.h>
using namespace std;

//点序号从1开始
const int MAXLEN=1001;
int N,M;
int root[MAXLEN];
int degree[MAXLEN];
int find_root(int x){
    if(root[x]==x)return x;
    x=find_root(root[x]);
    return x;

}

void join(int x,int y){
    int x_r=find_root(x);
    int y_r=find_root(y);
    if(x_r==y_r)return;
    root[x_r]=y_r;
}

void init(){
    for(int i=0;i<MAXLEN;++i)
    {root[i]=i;
    degree[i]=0;}

}
int main()
{
    int from,to;
    while(scanf("%d",&N)!=EOF){
        if(N==0)break;
        scanf("%d",&M);
        init();
        for(int i=0;i<M;++i){
            scanf("%d%d",&from,&to);
            join(from,to);
            degree[from]+=1;
            degree[to]+=1;
        }
        bool is_=true;
        //check connect and even
        int comp=0,r_1=find_root(1);
        for(int i=1;i<=N;++i){
            //cout<<find_root(i)<<" "<<degree[i];
            if(degree[i]==0)continue;//度为0孤立点,直接不用管
            if(find_root(i)!=r_1 || degree[i]%2!=0){
            is_=false;
                break;
            }
        }
        if(is_){
            printf("1\n");
            continue;
        }
        printf("0\n");

    }
    return 0;
}

发表于 2022-01-29 16:20:31 回复(0)
#include<bits/stdc++.h>
using namespace std;

const int MAX=1000;
int father[MAX];
int height[MAX];
int visitNode[MAX];
void Initial(int n){

	for(int i=0;i<=n;i++){
		father[i]=i;
		height[i]=0;
        visitNode[i]=0;
	}
	return ;
}

int Find(int x){
	if(x!=father[x]){
		father[x]=Find(father[x]);
	}
	return father[x];
}

void Union(int x,int y){
	x=Find(x);
	y=Find(y);
	if(x!=y){
		if(height[x]<height[y]){
			father[x]=y;
		}else if(height[y]<height[x]){
			father[y]=x;
		}else{
			father[y]=x;
			height[x]++;
		}
	}
	return ;
}

int main(){
	int n,m;
	while(cin>>n>>m){
		Initial(n);
		int indegree[n];
        fill(indegree,indegree+n,0);
		if(n==0) break;
		while(m--){
			int x,y;
			cin>>x>>y;
            if(x==y){
                continue;
            }
			indegree[x]++;
			indegree[y]++;
            visitNode[x]=1;visitNode[y]=1;
			Union(x,y);
		}
		int count=0,flag=0;
		for(int i=1;i<=n;i++){
			if(father[i]==i&&visitNode[i]==1){
				count++;
			}
			if(indegree[i]!=2&&visitNode[i]==1){
				cout<<"0"<<endl;
				flag=1;
				break;
			}
		}
		
		if(count==1&&flag==0){
			cout<<"1"<<endl;
		} 
	}
}

编辑于 2024-03-26 21:56:25 回复(0)
不需要考虑连通集的问题
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <climits>
using namespace std;
const int MAXN = 1010;
// 欧拉回路:并且每个顶点的度数都为偶数
// dfs判断下,度数使用
int visited[MAXN], rd[MAXN], G[MAXN][MAXN];
int n, m;
int isOk = 1;

void dfs(int i) {
	if (visited[i] != -1) {
		return;
	}
	visited[i] = 1;
	if (rd[i] % 2 != 0) {
		isOk = 0;
		return;
	}
	for (int j = 1; j <= n; j++) {
		if (visited[j] == -1 && G[i][j] != -1) {
			dfs(j);
		}
	}
}

int main() {
	while (cin >> n && n != 0) {
		cin >> m;
		memset(G, -1, sizeof G);
		memset(visited, -1, sizeof visited);
		int a, b;
		while (m--) {
			cin >> a >> b;
			if (a == b) {
				continue;
			}
			G[a][b] = 1;
			G[b][a] = 1;
			rd[a]++;
			rd[b]++;
		}
		for(int i = 1;i <= n;i++){
			dfs(i);
		}
		if (!isOk) {
			cout << 0 << endl;
		} else {
			cout << 1 << endl;
		}
	}
	return 0;
}


编辑于 2024-03-10 21:55:44 回复(0)
//统计每个结点的度,通过奇点(度为奇数的点)是否存在判断欧拉回路是否存在
//若奇点存在,则欧拉回路不存在,否则欧拉回路存在
#include <iostream>
#include <vector>
using namespace std;

const int MAXN = 1000;

vector<int>degree(MAXN);    //每个结点的度

int main() {
    int n, m;
    while (cin >> n >> m) {
        while (m--) {
            int from, to;       //起点和终点
            cin >> from >> to;
            degree[from]++;
            degree[to]++;
        }
        bool exist = true; //判断欧拉回路是否存在
        for (int i = 1; i <= n; i++) {
            if (degree[i] % 2 != 0) {
                exist = false;  //存在奇点(度为奇数的点),则不存在欧拉回路
                break;
            }
        }
        cout << static_cast<int>(exist) << endl;    //bool->int
    }
    return 0;
}

编辑于 2024-03-02 12:51:02 回复(0)
注意到只需要访问所有的边,而不需要访问所有的点,所以不用考虑连通性。
访问一个结点必须有进还有出,否则只进不出,不能够回到源点。综上,只需满足:所有结点的度均为偶数即可(0也是偶数)

#include <iostream>
#include <cstring>
using namespace std;

const int MAXN = 1001;
int E[MAXN];    //存储每个结点有多少边
int main() {
    int n,m;    //包含若干测试用例
    while(scanf("%d",&n) != EOF){
        if (n == 0){
            break;  //结束
        }
        scanf("%d",&m);
        memset(E,0,sizeof(E));
        for (int i = 0;i < m;++i){
            int u,v;
            scanf("%d%d",&u,&v);
            E[u]++, E[v]++;
        }
        //所有结点的度都为偶数,则返回1,否则返回0
        bool judge = true;
        for (int i = 1; i <= n; ++i ){
            if (E[i]%2 != 0){
                judge = false;
                break;
            }
        }
        if (judge){
            printf("1\n");
        }else{
            printf("0\n");
        }
    }
}



发表于 2023-03-24 00:34:38 回复(0)
#include <iostream>
#include <cstring>
using namespace std;

int *ufs = nullptr; // 并查集

int find(int a) // 查找
{
    if (a != ufs[a])
        ufs[a] = find(ufs[a]); // 路径压缩
    return ufs[a];
}

void unio(int a, int b) // 合并
{
    a = find(a);
    b = find(b);
    if(a != b)
        ufs[b] = a;
}

int main() {
    int N, M;
    while (cin >> N >> M) { // 注意 while 处理多个 case
        if(ufs) // 释放之前的用例的空间
            delete[] ufs;

        ufs = new int[N];
        int degrees[N];
        for (int i = 0; i < N; ++i) // 初始化并查集和度数
        {
            ufs[i] = i;
            degrees[i] = 0;
        }

        for(int i = 0; i < M; ++i) // 构建并查集,计算度数
        {
            int a, b;
            cin >> a >> b;
            ++degrees[a];
            ++degrees[b];
            unio(a, b);
        }
        
        int t = 0, rst = 1;
        for(int i = 0; i < N; ++i)
        {
            if(degrees[i] == 0) // 孤点
                continue;
            if(degrees[i] & 1) // 非孤点且度为奇数,不存在欧拉回路
            {
                rst = 0;
                break;
            }
            if(t == 0) // 不是孤点,且是找到的第一个连通子图,找到这个图的根
                t = find(i);
            else if(find(i) != t) // 有多个非孤点的连通子图,不存在欧拉回路
            {
                rst = 0;
                break;
            }
        }
        cout << rst << endl;
    }
    return 0;
}
// 64 位输出请用 printf("%lld")

发表于 2023-03-22 00:11:01 回复(0)
//由不间断的一笔画完可以想到深度优先,同时利用并查集辅助查找下一个目标城市,这是一开始的想法
//但测试用例总有一个过不了,后来看了看欧拉回路的定义才知道其他更好的做法
#include "stdio.h"
int N,M;
int father[1000];
int degree[1000];
bool isAppear[1000];

int find(int x){
    if(father[x] != x){
        father[x] = find(father[x]);
    }
    return father[x];
}

void Init(){
    for (int i = 1; i <= N; ++i) {
        father[i] = i;
        degree[i] = 0;
        isAppear[i] = false;
    }
}

int main(){
    while (scanf("%d",&N) != EOF){
        if(N == 0)
            break;
        scanf("%d",&M);
        Init();
        int c1,c2;
        for (int i = 0; i < M; ++i) {
            scanf("%d%d",&c1,&c2);
            if(c1 == c2)
                continue;
            ++degree[c1];
            ++degree[c2];
            if(find(c1) != find(c2))
                father[find(c1)] = c2;
            isAppear[c1] = true;
            isAppear[c2] = true;
        }
        int count = 0;
        for (int i = 1; i <= N; ++i) {
            if(father[i] == i && isAppear[i] == true)
                ++count;
        }
        if(count != 1)
            printf("0\n");
        else{
            count = 0;
            for (int i = 1; i <= N; ++i) {
                if(degree[i]%2 == 1)
                    ++count;
            }
            if(count == 0)
                printf("1\n");
            else
                printf("0\n");
        }
    }
}

发表于 2023-03-16 16:02:45 回复(0)
并查集解法看不懂,用DFS好理解一点
用DFS搜索边,若已搜索的边数==总边数 且 最后一条边指向起点,则存在欧拉回路:
#include <iostream>
#include <vector>
using namespace std;

struct Edge
{
    int v[2];   //该边连接的两个点
};

//src起点,i当前点,m总边数,count当前边数
bool dfs(vector<vector<int>> &graph, vector<Edge> &edge, vector<bool> &visited, int src, int i, int m, int count)
{
    //遍历相邻边
    for (int &e : graph[i])
    {
        if (visited[e] == true)
            continue;
        
        visited[e] = true;

        //j为该边的另一个结点
        int j = edge[e].v[0] == i ? edge[e].v[1] : edge[e].v[0];

        //已搜索的边数==总边数 且 最后一条边指向起点,则存在欧拉回路
        if (count + 1 == m && j == src)
            return true;

        //继续向下搜索
        if (dfs(graph, edge, visited, src, j, m, count+1))
            return true;

        visited [e] = false;
    }
    return false;
}

int main() {
    int n, m;
    while (cin >> n >> m)
    {
        if (n == 0)
            break;

        vector<vector<int>> graph(n);   //邻接表,存储的是相邻的边在edge中的下标
        vector<Edge> edge(m);   //存储所有的边
        for (int i = 0; i < m; i++)
        {
            Edge e;
            cin >> e.v[0] >> e.v[1];
            e.v[0]--; e.v[1]--; //结点号从0开始吧~
            edge[i] = e;
            graph[e.v[0]].push_back(i);
            graph[e.v[1]].push_back(i);
        }

        vector<bool> visited(m, false);

        cout << dfs(graph, edge, visited, 0, 0, m, 0) << endl;
    }
}


发表于 2023-03-07 17:09:56 回复(0)
使用欧拉回路充要条件,所有节点的度数皆为偶数。使用邻接矩阵存储图,只需要遍历每一行把每一行相加判断是否为偶数即可(对角线上的元素需要再加一次,因为出度和入度都算度的一部分)
#include<iostream>
#include<vector>
using namespace std;
bool have_oula_circuit(vector<vector<int>>& graph){
    for(int i = 0;i < graph.size();i++){
        int sum = 0;
        for(int j = 0;j < graph.size();j++){
            sum += graph[i][j];
        }
        if(graph[i][i]) sum++;
        if(sum % 2) return false;
    }
    return true;
}
int main(){
    int n, m;
    while(cin >> n >> m && n){
        vector<vector<int>> graph(n, vector<int>(n, 0));
        while(m--){
            int l, r;
            cin >> l >> r;
            graph[l - 1][r - 1] = 1;
            graph[r - 1][l - 1] = 1;
        }
        bool b = have_oula_circuit(graph);
        if(b) cout << 1 << endl;
        else cout << 0 << endl;
    }
    
}


发表于 2022-05-17 23:02:51 回复(0)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <cctype>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <cstring>
#include <iomanip>
#include <sstream>

using namespace std;

#pragma warning(disable:4996)
#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define repr(i, a, b) for(int i = a; i >= (b); --i)
#define trav(a, x) for (auto& a : x)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

const int INF = 0x3f3f3f3f;
const int maxn = 1005;
int n, m;
bool flag = false;
void dfs(vector<int> G[], int count, map<pair<int, int>, bool > &mp, int s) {
    if ((s == 1 && count == m) || flag == true) {
        flag = true;
        return;
    }
    rep(i, 0, sz(G[s]))
        if (mp[{s, G[s][i]}] == false ) {
            mp[{s,G[s][i]}] = mp[{G[s][i], s}] = true;
            dfs(G, count + 1, mp, G[s][i]);
            mp[{s,G[s][i]}] = mp[{G[s][i], s}] = false;            
        }
}
int main(){
    while (cin >> n) {
        if (n == 0)
            break;
        cin >> m;
        vector<int> G[maxn];
        rep(i, 0, m) {
            int f, t;
            cin >> f >> t;
            G[f].push_back(t);
            G[t].push_back(f);
        }
        flag = false;
        map<pair<int, int>, bool > mp;
        dfs(G, 0, mp, 1);
        cout << flag << endl;
    }
    return 0;
 }

发表于 2022-03-16 13:05:06 回复(0)
import java.util.*;
/**
牛客这是在逗我?不连通还可以有欧拉回路?
建议这道题直接去HDU1878提交,这个测试用例不敢苟同。
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1878

1、欧拉回路充要条件:
(1)连通图
(2)所有顶点的度为偶数
-------------------------
2、欧拉通路充要条件:
(1)连通图
(2)至多有一个度为奇数的节点
*/
public class Main{
    private static int N;
    private static int M;
    private static int[] Degree;
    private static int[] father;
    public static void init(){
        for(int i = 1; i <= N; i++)
            father[i] = i;
    }
    public static int getFather(int x){
        if(father[x] != x)
            father[x] = getFather(father[x]);
        return father[x];
    }
    public static void Union(int x, int y){
        int xx= getFather(x);
        int yy = getFather(y);
        if(xx != yy)
            father[yy] = xx;
    }
    public static boolean isOlaGraph(){
        int subGraph = 0;
        for(int i = 1; i <= N; i++)
            if(father[i] == i)
                subGraph++;
        if(subGraph != 1)
            return false;
        for(int i = 1; i <= N; i++)
            if((Degree[i] & 1) == 1)
                return false;
        return true;
    }
    public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        while(in.hasNext()){
            N = in.nextInt();
            if(N == 0)
                break;
            M = in.nextInt();
            Degree = new int[N + 1];
            father = new int[N + 1];
            init();
            for(int i = 0; i < M; i++){
                int x = in.nextInt();
                int y = in.nextInt();
                Degree[x]++;
                Degree[y]++;
                Union(x, y);
            }
            System.out.println(isOlaGraph() ? 1 : 0);
        }
    }
}

发表于 2021-06-18 12:36:24 回复(0)

问题信息

难度:
47条回答 13048浏览

热门推荐

通过挑战的用户

查看代码
欧拉回路