测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是节点数N ( 1 < N < 1000 )和边数M;随后的M行对应M条边,每行给出一对正整数,分别是该条边直接连通的两个节点的编号(节点从1到N编号)。当N为0时输入结束。
每个测试用例的输出占一行,若欧拉回路存在则输出1,否则输出0。
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; }
#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; } }
判断各个节点的度是否为偶数,自环增加度为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
#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&°ree[i]) root++; } if(root==1) printf("1\n"); else printf("0\n"); } }
/*也真是呵呵了。针对无向图欧拉回路的各种判别不一,我认为相对正确的一种说法是下面这种:无向图存在欧拉回路的充要条件一个无向图存在欧拉回路,当且仅当该图所有顶点度数都为偶数,且该图是连通图。 为什么呵呵:这道题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(); } }
确定无向图欧拉回路的充要条件:除孤立节点外,其它节点满足 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; }
#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); } }
/* 欧拉回路:首先对于无向图而言,欧拉回路指的是通过所有的边有且仅有一次,然后可以回到原点的图 需要满足两个要求: ①图是连通图=》采用并查集进行判断 ②图中所有顶点的度数(入度+出度)均为偶数=》采用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 */
#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; }
//无向图判断是否有欧拉回路 //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; }
#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; } } }
#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; }
//统计每个结点的度,通过奇点(度为奇数的点)是否存在判断欧拉回路是否存在 //若奇点存在,则欧拉回路不存在,否则欧拉回路存在 #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; }
#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"); } } }
#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")
//由不间断的一笔画完可以想到深度优先,同时利用并查集辅助查找下一个目标城市,这是一开始的想法 //但测试用例总有一个过不了,后来看了看欧拉回路的定义才知道其他更好的做法 #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"); } } }
#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; } }
#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; } }
#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; }
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); } } }