32-一笔画(欧拉图)

   http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=42       

                一笔画问题

时间限制:3000 ms  |  内存限制:65535 KB
难度:4
 
描述

zyc从小就比较喜欢玩一些小游戏,其中就包括画一笔画,他想请你帮他写一个程序,判断一个图是否能够用一笔画下来。

规定,所有的边都只能画一次,不能重复画。

 
输入
第一行只有一个正整数N(N<=10)表示测试数据的组数。
每组测试数据的第一行有两个正整数P,Q(P<=1000,Q<=2000),分别表示这个画中有多少个顶点和多少条连线。(点的编号从1到P)
随后的Q行,每行有两个正整数A,B(0<A,B<P),表示编号为A和B的两点之间有连线。
输出
如果存在符合条件的连线,则输出"Yes",
如果不存在符合条件的连线,输出"No"。
样例输入
2
4 3
1 2
1 3
1 4
4 5
1 2
2 3
1 3
1 4
3 4
样例输出
No
Yes
来源
[张云聪]原创
上传者
张云聪
解题思路:由题意可知为欧拉图(当然我是参考了别人的才知道,呵呵...)
欧拉图:通过图(无向图或有向图)中所有边一次且仅一次行遍图中所有顶点的通路称为欧拉通路,通过图中所有边一次且仅一次行遍所有顶点的回路称为欧拉回路。具有欧拉回路的图称为欧拉图(Euler Graph),具有欧拉通路而无欧拉回路的图称为半欧拉图。
首先用数组构建无向图,然后记录同一结点出现的次数,用于判断是否为欧拉图
欧拉图的性质(无向图):
1.无向连通图G是欧拉图,当且仅当G不含奇数度结点(G的所有结点度数为偶数);
2.无向连通图G含有欧拉通路,当且仅当G有零个或两个奇数度的结点;
如果满足欧拉图性质,然后进行dfs,如果深搜次数等于顶点个数即为连通图。
综上:能一笔画完的图必定满足的条件:1.该图是连通的
                 2.该图的奇度数节点为0或2

这里用了dfs遍历,由于用二维数组记录图,所以造成很多无谓的访问和判断,效率不是很高,不过还是a了,建议使用邻接表记录图
判断连通图:可以并查集和dfs
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
vector <int> mp[1005];
int visit[1005];
int du[1005];

void dfs(int s){
	visit[s] = 1;
	int len = mp[s].size();
	for(int i = 0; i < len; i++){
		if(!visit[mp[s][i]]){
			dfs(mp[s][i]);
		} 
	} 
}

int main(){
	int n, m;
	int t;
	cin >> t;
	while(t--){
		memset(visit, 0, sizeof(visit));
		memset(du, 0, sizeof(du)); 
		cin >> n >> m;
		
		for(int i = 1; i <= n; i++)
			mp[i].clear();
		for(int i = 0; i < m; i++){
			int x, y;
			cin >> x >> y;
			mp[x].push_back(y);
			mp[y].push_back(x);
			du[x]++;
			du[y]++;
		} 
		dfs(1);
		for(int i = 1; i <= n; i++){
			if(!visit[i]){
				cout << "No" << endl;
				return 0; 
			}
		}
		int ct = 0;
		for(int i = 1; i <= n; i++){
			if(du[i] & 1)
				ct++;
		}
		if(ct == 0 || ct == 2){
			cout << "Yes" << endl; 
		}
		else
			cout << "No" << endl;
	}
	
	return 0;
}

  

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
int mp[1005];
int ans[1005];

int find(int x){
	if(mp[x] == x)
		return x;
	else
		mp[x] = find(mp[x]);
}

void mix(int x, int y){
	int xx = find(x);
	int yy = find(y);
	if(xx == yy)
		return ;
	else
		mp[x] = yy;
}

int main(){
	int t;
	cin >> t;
	while(t--){
		memset(ans, 0, sizeof(ans));
		int n, m;
		cin >> n >> m;
		for(int i = 1; i <= n; i++){
			mp[i] = i;
		}
		for(int i = 0; i < m; i++){
			int x, y;
			cin >> x >> y;
			mix(x, y);
			ans[x]++;
			ans[y]++; 
		}
		int ct = 0;
		int du = 0;
		for(int i = 1; i <= n; i++){
			if(mp[i] == i)
				ct++;
			if(ans[i] & 1)
				du++;
		}
		if(ct == 1 && (du == 0 || du == 2))
			cout << "Yes" << endl;
		else
			cout << "No" << endl;
	}
	
	return 0;
}

  

 
原文地址:https://www.cnblogs.com/zhumengdexiaobai/p/8624822.html