题目地址。
解题报告:
欧拉回路:图G,若存在一条路,经过G中每条边有且仅有一次,称这条路为欧拉路,如果存在一条回路经过G每条边有且仅有一次,
称这条回路为欧拉回路。具有欧拉回路的图成为欧拉图。
判断欧拉路是否存在的方法
有向图:图连通,有一个顶点出度大入度1,有一个顶点入度大出度1,其余都是出度=入度。
无向图:图连通,只有两个顶点是奇数度,其余都是偶数度的。
判断欧拉回路是否存在的方法
有向图:图连通,所有的顶点出度=入度。
无向图:图连通,所有顶点都是偶数度。
本题呢。先用并查集查看共有几棵树, 记录下每棵树中度为奇数的点的个数。 如果该树中度为奇数的点的个数为0, 且代表元的度为0,证明该点为孤立的点,按题目要求的略过就可以了。如果代表元的度不为0, 且该树中度为奇数的店为0,那么证明为欧拉回路,1组就能搞定;如果这两种情况都不属于,那么浏览该树中的点要用奇数点的个数/2
代码如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXN 100005 //degree为度,p为并查集,cnt为记录该树中度为奇数的点的个数 int degree[MAXN], p[MAXN], cnt[MAXN], hash[MAXN], q[MAXN]; int find(int x){return p[x] == x ? x : (p[x]=find(p[x]));} void Union(int u, int v){ int x = find(u), y = find(v); if(x != y){ p[x] = y; } } int main(){ int n, m, i, a, b, top; while(scanf("%d %d", &n, &m) == 2){ top = 0; for(i=1; i<=n; i++){ cnt[i] = degree[i] = hash[i] = 0; p[i] = i; } for(i=1; i<=m; i++){ scanf("%d %d", &a, &b); Union(a, b); degree[a]++; degree[b]++; } for(i=1; i<=n; i++){ int k = find(i); //查找代表元 if(!hash[k]){ //如果该代表元没有被访问过 q[top++] = k; //将该代表元存起来 hash[k]=1; } if(degree[i] % 2) cnt[k]++; } int sum = 0; for(i=0; i<top; i++){ int k = q[i]; if(degree[k] == 0) continue; //孤立的点 if(cnt[k] == 0) sum++; //欧拉回路 else sum += (cnt[k] / 2); } printf("%d\n", sum); } return 0; }