• 【Ant Trip】题解


    题目描述


    给你无向图的n个点和m条边,保证这m条边都不同且不会存在同一点的自环边,现在问你至少要几笔才能所有边都画一遍。(一笔画的时候笔不离开纸)


    输入格式
    多组数据,每组数据用空行隔开。
    对于每组数据,第一行两个整数n, m表示点数和边数。接下去m行每行两个整数a, b,表示a, b之间有一条边。


    输出格式
    对于每组数据,输出答案。


    样例输入
    3 3
    1 2
    2 3
    1 3
    4 2
    1 2
    3 4


    样例输出


    1
    2


    分析

    做这道题,首先我们需要知道这些:

    • 若一张图只有一个点,那么一笔都不需要画
    • 假如他是一个半欧拉图,那么也只需要一笔
    • 以上两种都不是的话,那么我们需要画的笔数应该等于这张图中度为奇数的点数之和除以 2

    那么我们怎么判断是否为一个欧拉图呢?暴搜?记得雷老师说过,假如一张图是欧拉图,那么他的所有点的度应该都是偶数。
    其实这道题的题目并没有说所给出的数据是一张连通图,所以我们又可以用一个并查集来求出每一个联通分量,并用一个数组来存储这个联通分量之中的度为奇数的点的个数(好像有点啰嗦)


    看懂了的话,可以自己实现一遍,发现有问题再看代码吧~

    代码

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 1e5 * 2 + 5;
    
    int fa[MAXN];
    int in[MAXN];
    int num[MAXN];
    int ans[MAXN];
    
    int Find (int x) {
    	if (fa[x] != x) fa[x] = Find (fa[x]);
    	return fa[x];
    }//找爸爸
    
    int main() {
    	int n, m;
    	while ((scanf("%d %d", &n, &m)) != EOF) {
    		for (int i = 1; i <= n; i++) fa[i] = i;
    		memset (num, 0, sizeof num);
    		memset (ans, 0, sizeof ans);
    		memset (in, 0, sizeof in);//每次都要初始化数组(错了好几次,害)
    		for (int i = 1; i <= m; i++) {
    			int x, y;
    			scanf("%d %d", &x, &y);
    			in[x] ++;
    			in[y] ++;//度累加
    			x = Find (x);
    			y = Find (y);
    			if (x != y) fa[x] = y;
                //假如他们不在一个联通分量之中,就把他们放进同一个
    		}
    		for (int i = 1; i <= n; i++) {
    			int x = Find (i); // i 的祖先。因为我们在之前是做了一个并查集的,假如说他们在一个连通分量之中,那么他们的祖先就应该是相同的
    			num[x] ++;//这个联通分量中的点数累加
    			if (in[i] % 2 == 1) ans[x] ++;//因为我们已经知道 i 是这个联通分量中的值了,所以在这里用 ans 数组来累加他所在的连通分量的度为奇数的点的个数
                //此处其实就是用祖先来作为下标方便储存,其实也可以在上面输入时合并 x 和 y 的时候就用一个 vector 数组来存储以 x 为祖先的一个集合,最后看那些集合是有数的,就做一遍下面的操作,请自己实现!
    		} 
    		int sum_ = 0;//用于累加答案
    		for (int i = 1; i <= n; i++) {
    			if (num[i] <= 1) continue;//假如只有 1 个点,就不用管(0 个更不用)
    			if (ans[i] == 0) sum_ ++;//假如这个连通分量之中所有点的度都没有奇数,说明有欧拉路,一笔画成
    			else sum_ += ans[i] / 2;//以上两种都不是的话,那么我们需要画的笔数应该等于这张图中度为奇数的点数之和除以 2
    		} 
    		printf("%d
    ", sum_);//完美结束
    	}
    	return 0;
    }
    
  • 相关阅读:
    注释总结
    C# Notes
    坑爹的Honor10开热点
    用热得快烧洗澡水
    跳转语句
    台湾书籍代购网址——2013-08-25 16
    【转】cocos2d-x 模仿计时器效果,动态增加分数——2013-08-25 16
    【转】C/C++中的日期和时间 TIME_T与STRUCT TM转换——2013-08-25 16
    【转】Cocos2d-x 2.0 拖尾效果深入分析
    cocos2d-x之CCMotionStreak类——2013-08-25 16
  • 原文地址:https://www.cnblogs.com/cqbzyanglin/p/13537844.html
Copyright © 2020-2023  润新知