码迷,mamicode.com
首页 > 其他好文 > 详细

杭电ACM3018——Ant Trip~~欧拉回路

时间:2015-04-30 09:05:10      阅读:136      评论:0      收藏:0      [点我收藏+]

标签:acm   杭电   欧拉   

这题,欧拉回路的应用,只是比较麻烦。

题目的意思是,一群蚂蚁,想要走遍给定的每一条边,但是,图不连通或者不存在欧拉回路的不可能走完,所以可以将人分组,求解最少的分组的数目。

解题的主要思路是:

1.将各点进行合并,使用并查集。

2.遍历并查集,查找各个连通图的奇数度的个数。

3.如果该连通图的奇数点为0,只需一笔。如果不是,就需要奇数点的数目 / 2。

还有一点需要注意的是,单个点应该无视他,题目有讲到。

题目有点坑,输入那里还有样例那里每一个测试样例有一个空行。可是实际上不需要空格,是的,不需要,坑了我两个PE。

下面是AC的代码,有详细注释:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX = 100005;
bool vis[MAX];                      //判断该顶点是否出现过
int par[MAX], degree[MAX], M, E;    //par为并查集,degree为各个顶点的度。
int temp[MAX];                     //各个连通图的奇数点个数

int finds(int x)                   //并查集的查找函数
{
	int r = x;
	while(r != par[r])
		r = par[r];
	int i = x, j;
	while(i != r)                 //压缩路径
	{
		j = par[i];
		par[i] = r;
		i = j;
	}
	return r;
}
void join(int x, int y)          //并查集合并函数
{
	int fx = finds(x);
	int fy = finds(y);
	if(fx != fy)
		par[fy] = fx;
}
int main()
{
	int a, b, i;
	bool flag = false;
	while(scanf("%d%d", &M, &E) != EOF)
	{
		memset(degree, 0, sizeof(degree));     //初始化各个数组
		memset(temp, -1, sizeof(temp));
		memset(vis, false, sizeof(vis));
		for(i = 0; i <= M; i++)
			par[i] = i;
		for(i = 0; i < E; i++)
		{
			scanf("%d%d", &a, &b);
			if(a == b)                          //顶点相同,直接跳过
				continue;
			if(a > b)
			{
				a = a ^ b;
				b = b ^ a;
				a = a ^ b;
			}
			join(a, b);                         //合并两个顶点
			degree[a]++; vis[a] = true;         //该点度+1,标记为该点存在
			degree[b]++; vis[b] = true;
		}
		int ans = 0;
		for(i = 1; i <= M; i++)                 //遍历每一个顶点
		{
			int j = finds(i);                   //查找属于哪个连通图
			if(temp[j] == -1)                   //该连通图是新的,也就是之前没查找到的,
				temp[j] = 0;                    //初始化奇数点为0。
			if(degree[i] % 2)                   //如果该点的度为奇数
				temp[j]++;                      //奇数点+1;
		}
		for(i = 1; i <= M; i++)                  //遍历每一个顶点
		{
			if(temp[i] > 0 && vis[i])            //奇数点 > 0 ,且该点出现过
				ans += temp[i] / 2;              //分组数加上奇数点 / 2;
			else if(temp[i] == 0 && vis[i])      //奇数点为0,该点出现过
				ans++;                           //分组数 + 1;
		}
		cout << ans << endl;
	}
	return 0;
}


杭电ACM3018——Ant Trip~~欧拉回路

标签:acm   杭电   欧拉   

原文地址:http://blog.csdn.net/qq_25425023/article/details/45372085

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!