南阳理工ACM42——一笔画问题

一笔画问题,也就是欧拉道路,这一题,简单的欧拉回路的应用。

什么是欧拉回路?

欧拉回路就是在图A中,存在一条路径使得每一条边都走过一次,并且这条路径是一个圈,就是欧拉回路。

欧拉回路的判断:

1.在有向图中:首先必要的条件是图连通,所以顶点的入度都等于出度。

2.在无向图中:首要条件还是图连通,其次就是所以顶点都是偶数度(该顶点的度为偶数)

这一题,还需要加上一个条件,也就是存在两个奇数度的点的情况,也是符合的,从一个奇数点出发,另外一个奇数点结束。

判断图是否连通,可以运用DFS或者并查集,都是很简单的。

下面是dfs的算法:

void dfs(int x)
{
	int i;
	vis[x] = 1;             //标记已返问过
	for(i = 1; i <= n; i++)
		if(map[x][i])
		{
			degree[x]++;    //该点度+1
			if(vis[i] == 0) //没返问过,递归
				dfs(i);
		}
}

下面是AC的代码,我用的是并查集来判连通:

#include <iostream>
#include <cstring>
using namespace std;
const int MAX_N = 1005;
int par[MAX_N], degree[MAX_N], n, v;

int finds(int x)
{
	if(x == par[x])
		return x;
	else
		return par[x] = finds(par[x]);
}

int main()
{
//	freopen("data.txt", "r", stdin);
	int t, a, b, i, j;
	cin >> t;
	while(t--)
	{
		cin >> n >> v;
		memset(degree, 0, sizeof(degree));
		for(j = 0; j <= n; j++)            //初始化并查集
			par[j] = j;
		for(i = 0; i < v; i++)
		{
			cin >> a >> b;
			degree[a]++; degree[b]++;      //该点度+1
			int next_a = finds(a);
			int next_b = finds(b);
			if(next_a != next_b)            //合并
				par[next_a] = next_b;
		}
		int flag = 0, tag = 0;
		for(i = 1; i <= n; i++)            //判连通
			if(par[i] == i)
				flag++;
		if(flag > 1)                       //不连通
			cout << "No" << endl;
		else                                //连通
		{
			for(i = 1; i <= n; i++)        //判奇数点
				if(degree[i] % 2)
					tag++;
			if(tag == 0 || tag == 2)
				cout << "Yes" << endl;
			else
				cout << "No" << endl;
		}
	}
	return 0;
}
时间: 2024-10-15 11:16:35

南阳理工ACM42——一笔画问题的相关文章

南阳理工 题目9:posters(离散化+线段树)

posters 时间限制:1000 ms  |  内存限制:65535 KB 难度:6 描述 The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally deci

南阳理工另一种阶乘问题

#include<stdio.h>int main(){  int n,m;  int sum,i;  int a[21];  int t=1,t1=1;  for(i=1;i<21;i=i+2)  {   a[i]=t*t1;   a[i+1]=a[i];   t=t1*t;   t1=t1+2;  }  scanf("%d",&n);  while(n--)  {   sum=0;   scanf("%d",&m);   for

南阳理工acm 1

C++版: #include<iostream> using namespace std; int main() { int a,b; cin>>a>>b; cout<<a+b<<endl; } 南阳理工acm 1,布布扣,bubuko.com

南阳理工--韩信点兵

#include<stdio.h>int main(){  int a,b,c;  int x;  scanf("%d%d%d",&a,&b,&c);  for(x=10;x<=100;x++)  {   if(x%3==a&&x%5==b&&x%7==c)   {    printf("%d\n",x);    break;   }  }  if(x>100)  {   printf(

(c++实现)南阳理工acm 题目117 求逆序数

求逆序数 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 现在,给你一个N个元素的序列,请你判断出它的逆序数是多少. 比如 1 3 2 的逆序数就是1. 输入 第一行输入一个整数T表示测试数据的组数(1<=T<=5) 每组测试数据的每一行是一个整数N表示数列中共有N个元素(2〈=N〈=1000000) 随后的一行共有N个整

南阳理工----奋斗的小蜗牛

#include<stdio.h>#include<math.h>int main(){  int t,h;  int n;  double n1;  scanf("%d",&t);  while(t--)  {   n=0;    scanf("%d",&h);    if(h<=10)    printf("%d\n",n+1);   if(h>10)    {  n1=(h-10)/5.0

南阳理工---题目975关于521

关于521 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 Acm队的流年对数学的研究不是很透彻,但是固执的他还是想一头扎进去. 浏览网页的流年忽然看到了网上有人用玫瑰花瓣拼成了521三个数字,顿时觉得好浪漫,因为每个男生都会不经意的成为浪漫的制造者.此后,流年走到哪里都能看到5.2.1三个数字,他怒了,现在他想知道在连续的数中有多少数全部包含了这三个数字.例如12356就算一个,而5111就不算.特别的,如果他看到了521三个数连续出现,会特别的愤怒.例如3521

南阳理工ACM111

分数加减法 时间限制:3000 ms  |  内存限制:65535 KB 难度:2 描述 编写一个C程序,实现两个分数的加减法 输入 输入包含多行数据 每行数据是一个字符串,格式是"a/boc/d". 其中a, b, c, d是一个0-9的整数.o是运算符"+"或者"-". 数据以EOF结束 输入数据保证合法 输出 对于输入数据的每一行输出两个分数的运算结果. 注意结果应符合书写习惯,没有多余的符号.分子.分母,并且化简至最简分数 样例输入 1/

南阳理工60---谁获得了最高奖学金

描述    某校的惯例是在每学期的期末考试之后发放奖学金.发放的奖学金共有五种,获取的条件各自不同: 1) 院士奖学金,每人8000元,期末平均成绩高于80分(>80),并且在本学期内发表1篇或1篇以上论文的学生均可获得: 2) 五四奖学金,每人4000元,期末平均成绩高于85分(>85),并且班级评议成绩高于80分(>80)的学生均可获得: 3) 成绩优秀奖,每人2000元,期末平均成绩高于90分(>90)的学生均可获得: 4) 西部奖学金,每人1000元,期末平均成绩高于85分