32-一笔画(欧拉图)
- 描述
-
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; }
版权声明:本文为zhumengdexiaobai原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。