思路
首先欧拉回路是一个连通图,这个可以用并查集的模板来写,下面详尽的写了并查集的一个模板,具体关于并查集的知识我就不叙述了。
然后还要满足所有顶点的度为偶数,这个因为已经给出了各条边,很容易求出来度数
其中需要注意以下几点:
- 自环不用算,因为去掉自环也不会产生影响,但是加上自环的话会让度数计算产生问题。
- 孤立点不用算,也就是度为 0 的点,孤立点首先不会对欧拉回路产生影响,但是却会增加连通分支数量。
- 代码尽管很长,但是前面一半都是一个并查集模板类,main 函数中的代码前面一半也只是做了一个初始化的工作,后面一半就是判断是否连通分量为 1 以及是否度均为偶数。
#include<iostream> #include<vector> #include<numeric> using namespace std; class UF { public: vector<int> fa; vector<int> sz; int comp_cnt; // 连通分量数目 int n; public: UF(int _n) : n(_n), comp_cnt(_n), fa(_n), sz(_n, 1){ iota(fa.begin(), fa.end(), 0); } int findFa(int x){ return x == fa[x] ? x : fa[x] = findFa(fa[x]); } void unite(int x, int y){ x = findFa(x); y = findFa(y); if(x == y) return; if(sz[x] < sz[y]) swap(x, y); fa[y] = x; sz[x] += sz[y]; comp_cnt --; } bool connected(int x, int y) { x = findFa(x); y = findFa(y); return x == y; } }; int main(){ int N, M; while(cin >> N && N){ cin >> M; vector<int> degree(N, 0); UF uf(N); int x, y; for(int i = 0; i < M; i ++){ cin >> x >> y; // 去掉自环 if(x == y) continue; uf.unite(x - 1, y - 1); degree[x - 1] ++; degree[y - 1] ++; } // 去掉孤立点也就是度为 0 的点 for(int d : degree) if(d == 0) uf.comp_cnt --; // 连通分量数目不为 1 if(uf.comp_cnt != 1) cout << 0 << endl; else{ // 检查是否存在度为奇数的点 bool flag = true; for(int d : degree) if(d % 2){ flag = false; cout << 0 << endl; break; } if(flag) cout << 1 << endl; } } }