题目链接:
思路分析:题目可以看做一笔画问题,求最少画多少笔可以把所有的边画一次并且只画一次;
首先可以求出该无向图中连通图的个数,在每个无向连通图中求出需要画的笔数再相加即为所求。在一个无向连通图中,如果所有的点的度数为偶数则存在一个欧拉回路,
则只需要画一笔即可;如果图中存在度数为奇数的点,则需要画的笔数为度数为奇数的点的个数 /2;需要注意的孤立的点不需要画;
代码如下:
#include#include #include using namespace std;const int MAX_N = 100000 + 100;int fa[MAX_N], odd[MAX_N];int link[MAX_N], set_count[MAX_N];void Init(){ for (int i = 0; i < MAX_N; ++i) { set_count[i] = 1; fa[i] = i; }}int Find(int num){ if (fa[num] == num) return num; else return fa[num] = Find(fa[num]);}int Union(int a, int b){ int fa_a = Find(a); int fa_b = Find(b); if (fa_a == fa_b) return -1; else if (fa_a > fa_b) { fa[fa_b] = fa_a; set_count[fa_a] += set_count[fa_b]; } else { fa[fa_a] = fa_b; set_count[fa_b] += set_count[fa_a]; } return 1;}int main(){ int vertex_num, road_num; int ver_1, ver_2; while (scanf("%d %d", &vertex_num, &road_num) != EOF) { int ans = 0; Init(); memset(link, 0, sizeof(link)); memset(odd, 0, sizeof(odd)); for (int i = 0; i < road_num; ++i) { scanf("%d %d", &ver_1, &ver_2); link[ver_1]++; link[ver_2]++; Union(ver_1, ver_2); } for (int i = 1; i <= vertex_num; ++i) { int fa = Find(i); if ((link[i] & 1) == 1) odd[fa]++; } for (int i = 1; i <= vertex_num; ++i) { if (fa[i] == i && set_count[i] != 1) { if (odd[i] == 0) ans++; else ans += odd[i] / 2; } } printf("%d\n", ans); } return 0;}