描述
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
题意:判断一个图形能否一笔画,是欧拉回路问题,对无向图而言,满足欧拉回路,第一要连通,第二是要么所有度数为偶数,要么有两个奇数度数节点作为起点和终点,
搜索,或者并查集都可以判断回路,记录度数判断即可。
#include <map> #include <set> #include <stack> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 1005; const int maxm = 2005; struct Edge { int from,to,next; }; Edge e[maxm]; int head[maxn]; int n,m; bool OK; bool vis[maxn]; queue<int> q; int cnt[maxn]; void InsertEdge(int from,int to,int index) { e[index].from=from; e[index].to=to; e[index].next=head[from]; head[from]=index; } void bfs(int rt) { int num=1; q.push(rt); vis[rt]=1; while(!q.empty()) { if(num == n) { OK=true; break;} int t = q.front(); q.pop(); for(int k=head[t]; k!=-1; k=e[k].next) { int to = e[k].to; if(!vis[to]) { q.push(to); num++; vis[to]=true; } } } } int main() { #ifdef LOCAL_DEBUG freopen("input.txt","r",stdin); #endif int T; scanf("%d",&T); while(T--) { memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); while(!q.empty()) q.pop(); memset(cnt,0,sizeof(cnt)); scanf("%d%d",&n,&m); int from,to; for(int i=0;i<2*m;i+=2) { scanf("%d%d" , &from ,&to); InsertEdge(from,to,i); InsertEdge(to,from,i^1); cnt[from]++; cnt[to]++; } OK=false; bfs(1); if(!OK) { printf("No\n"); continue; } int ans=0; for(int i=1;i<=n;i++) { if(cnt[i]%2!=0) ans++; } if(ans==0 || ans==2) { printf("Yes\n"); } else { printf("No\n"); } } return 0; }