ACM题目————一笔画问题
描述
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
可以用并查集做,也可以直接建图做。
因为正在加班加点的学习数据结构,于是先建图做了一次。
参考了http://www.cnblogs.com/dongsheng/archive/2012/06/04/2534489.html
建图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | //Asimple #include <stdio.h> #include <iostream> #include <algorithm> using namespace std; const int maxn = 1005; int n, T, num, cnt, point, line, x, y; int G[maxn][maxn]; int vis[maxn]; //标记数组,标记是否走过 int p[maxn]; //每个节点的度 //图的DFS //欧拉图:节点度数全部为偶数 //半欧拉图:有且只有两个度数为奇数的节点 //这两种图都可以一笔画出。 void DFS( int i) { int v; vis[i] = 1 ; for (v=0; v<point; v++) if ( v!=i && G[i][v] && !vis[v]) DFS(v); } int main() { cin >> T ; while ( T -- ) { cnt = 0 ; bool flag = true ; cin >> point >> line ; memset (p,0, sizeof (p)); memset (vis,0, sizeof (vis)); memset (G,0, sizeof (G)); for ( int i=0; i<line; i++) { cin >> x >> y ; G[x-1][y-1] = G[y-1][x-1] = 1 ; //建图 ++ p[x-1] ; ++ p[y-1] ; //统计 各节点的度 } DFS(0); //判断是否连通 for ( int i=0; i<point; i++) { G[i][i] = 1 ; if ( vis[i]==0 ) flag = false ; if ( p[i]&1 ) cnt ++ ; } if ( flag ) //是连通图 { if ( cnt==0 || cnt==2 ) cout << "Yes" << endl ; else cout << "No" << endl ; } else cout << "No" << endl ; } return 0; } |
并查集:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | #include <cstdio> #include <iostream> #include <cstring> using namespace std; int father[1005], deg[1005]; int find( int k) { if (k == father[k]) return k; else return father[k] = find(father[k]); } int main() { int T, p, q, a, b; scanf ( "%d" , &T); while (T--) { scanf ( "%d%d" , &p, &q); for ( int i = 1; i <= p; ++i) { father[i] = i; deg[i] = 0; } while (q--) { scanf ( "%d%d" , &a, &b); ++deg[a]; ++deg[b]; int fa = find(a); int fb = find(b); if (fa != fb) father[fa] = fb; } int cnt1, cnt2; cnt1 = cnt2 = 0; for ( int i = 1; i <= p; ++i) { if (father[i] == i) { ++cnt1; if (cnt1 > 1) break ; } if (deg[i] & 1) ++cnt2; } if (cnt1 > 1) printf ( "No\n" ); else { if (cnt2 == 0 || cnt2 == 2) printf ( "Yes\n" ); else printf ( "No\n" ); } } return 0; } |
低调做人,高调做事。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理