PTA甲1126 Eulerian Path (25 point(s))

强烈推荐,刷PTA的朋友都认识一下柳神–PTA解法大佬

本文由参考于柳神博客写成

柳神的CSDN博客,这个可以搜索文章

柳神的个人博客,这个没有广告,但是不能搜索

还有就是非常非常有用的 算法笔记 全名是

算法笔记  上级训练实战指南		//这本都是PTA的题解算法笔记

PS 今天也要加油鸭

在这里插入图片描述

一些有意思的彩蛋:

这题在写之前强烈推荐看下这个视频,个人觉得蛮有意义的,描述了图论的起源

欧拉路径

题目原文

In graph theory, an Eulerian path is a path in a graph which visits every edge exactly once. Similarly, an Eulerian circuit is an Eulerian path which starts and ends on the same vertex. They were first discussed by Leonhard Euler while solving the famous Seven Bridges of Konigsberg problem in 1736. It has been proven that connected graphs with all vertices of even degree have an Eulerian circuit, and such graphs are called Eulerian. If there are exactly two vertices of odd degree, all Eulerian paths start at one of them and end at the other. A graph that has an Eulerian path but not an Eulerian circuit is called semi-Eulerian. (Cited from https://en.wikipedia.org/wiki/Eulerian_path)

Given an undirected graph, you are supposed to tell if it is Eulerian, semi-Eulerian, or non-Eulerian.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 2 numbers N (≤ 500), and M, which are the total number of vertices, and the number of edges, respectively. Then M lines follow, each describes an edge by giving the two ends of the edge (the vertices are numbered from 1 to N).

Output Specification:

For each test case, first print in a line the degrees of the vertices in ascending order of their indices. Then in the next line print your conclusion about the graph – either Eulerian, Semi-Eulerian, or Non-Eulerian. Note that all the numbers in the first line must be separated by exactly 1 space, and there must be no extra space at the beginning or the end of the line.

Sample Input 1:

7 12
5 7
1 2
1 3
2 3
2 4
3 4
5 2
7 6
6 3
4 5
6 4
5 6

Sample Output 1:

2 4 4 4 4 4 2
Eulerian

Sample Input 2:

6 10
1 2
1 3
2 3
2 4
3 4
5 2
6 3
4 5
6 4
5 6

Sample Output 2:

2 4 4 4 3 3
Semi-Eulerian

Sample Input 3:

5 8
1 2
2 5
5 4
4 1
1 3
3 2
3 4
5 3

Sample Output 3:

3 3 4 3 3
Non-Eulerian

生词如下:

不太想看,生词有点小多,有点烦的

Eulerian Path 欧拉回路,是一个定义

circuit 环

even 偶数

odd 奇数

degrees 度数

ascending 上升

indices 指数

一句一句慢慢分析吧(因为我看不懂,所以就用最笨的办法吧)

In graph theory, an Eulerian path is a path in a graph which visits every edge exactly once. Similarly, an Eulerian circuit is an Eulerian path which starts and ends on the same vertex.

在图论中,欧拉路径是图中的一条路径,它只访问每条边一次。
类似地,欧拉回路是在同一顶点开始和结束的欧拉路径。

They were first discussed by Leonhard Euler while solving the famous Seven Bridges of Konigsberg problem in 1736

莱昂哈德·欧拉 (Leonhard Euler) 在 1736 年解决著名的柯尼斯堡七桥问题时首次讨论了它们

It has been proven that connected graphs with all vertices of even degree have an Eulerian circuit, and such graphs are called Eulerian

已经证明,所有偶数顶点的连通图都有欧拉回路,这种图称为欧拉回路

If there are exactly two vertices of odd degree, all Eulerian paths start at one of them and end at the other

如果恰好有两个奇数顶点,则所有欧拉路径都从其中一个开始并在另一个结束

A graph that has an Eulerian path but not an Eulerian circuit is called semi-Eulerian. (Cited from https://en.wikipedia.org/wiki/Eulerian_path)

有欧拉路径但没有欧拉回路的图称为半欧拉图。
(引自 https://en.wikipedia.org/wiki/Eulerian_path)

iven an undirected graph, you are supposed to tell if it is Eulerian, semi-Eulerian, or non-Eulerian.

给定一个无向图,您应该判断它是欧拉图、半欧拉图还是非欧拉图。

For each test case, first print in a line the degrees of the vertices in ascending order of their indices.

对于每个测试用例,首先按顶点索引的升序在一行中打印顶点的度数。

题目大意:

就是考察了一个欧拉回路的定义

一个图中,走完全部的顶点,而且路径全部要走过,而且只能走一遍 如果能走完的话,那就是欧拉的

如果开始的顶点和结束的顶点是一样的话,那就是完全欧拉回路,如果不是一样的话,就是semi回路

这里用到了一个数学知识点

具体解释在视频下面

思路如下:

先判断一个是不是连通图,不是的话,直接出否

如果是的话,在判断节点度数

一句话总结:Copy柳神

如果一个连通图的所有结点的度都是偶数,那么它就是Eulerian,如果除了两个结点的度是奇数其他都是偶数,那么它就是Semi-Eulerian,否则就是Non-Eulerian~

代码如下:

#include
#include
using namespace std;
int cnt = 0,even=0;
vector<bool> visit;
vector<vector<int>> v;
//深度优先搜索
void dfs(int index) {
	visit[index] = true;
	cnt++;
	for (int i = 0; i < v[index].size(); i++)
		if (visit[v[index][i]] == false)
			dfs(v[index][i]);
}
int main(void) {
	int N, M;
	scanf("%d%d", &N, &M);
	v.resize(N + 1);
	visit.resize(N + 1);
	int t1, t2;
	for (int i = 0; i < M; ++i) {
		scanf("%d%d", &t1, &t2);
		v[t1].push_back(t2);
		v[t2].push_back(t1);
	}
	for (int i = 1; i <= N; ++i) {
		if (i != 1)	printf(" ");
		printf("%d", v[i].size());
		if (v[i].size() % 2 == 0)	++even;
	}
	printf("\n");
	dfs(1);
	if (even == N && cnt == N)
		printf("Eulerian");
	else if (even == N - 2 && cnt == N)
		printf("Semi-Eulerian");
	else
		printf("Non-Eulerian");
	return 0;
}

这题用过了DFS了,让我们来写一哈BFS吧

BFS也是差不多的

改动了一点点

改动代码如下:

记得加歌queue的头文件

void bfs(int index) {
	queue<int> q;
	q.push(index);
	visit[index] = true;
	++cnt;
	while (!q.empty()) {
		int t = q.front();
		q.pop();
		for (int i = 0; i < v[t].size(); ++i) {
			if (visit[v[t][i]] == false) {
				visit[v[t][i]] = true;
				cnt++;
				q.push(v[t][i]);
			}
		}
	}
}

完结撒花

你可能感兴趣的:(PTA甲级)