nyoj 一笔画(并查集)
来源:互联网 发布:带网络驱动精灵 编辑:程序博客网 时间:2024/04/30 12:38
一笔画问题
时间限制: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"。 - 样例输入
24 31 21 31 44 51 22 31 31 43 4
- 样例输出
NoYes
上篇用的是深搜,但是这一笔画不用并查集做就不叫做过这一笔画
而且建图的话 数组开的太大,数组的利用率也不高,如果数据较大,那不敢相信;
还是要用一下并查集了,而且这是学习并查集的好机会
简单的并查集
开一个数组,然后将数组初始化
初始化就是将数组里的值改为下标的值
如 a1 里面的值为1 a2 的值为2;
然后 当后面输入 路径(两点连接情况)时,
如果两个点相连,将数组里面的数变为同一个数
如 1 - 3
那么把 a1 和a3 里面的数变为 1 (3也可以,不过后面的都要这样变)
再来一组 1- 4 a1 a4都要变成1(或者3)
数组里面数相同的表示同一个数
如果来一组 2 - 6 那么 a2 与 a6 都为 2 (或者为6)
这样 目前有两组了;
下面先具体实现用此方法的 判断连通图
#include<stdio.h>int point,line;int a[1005],m[1005],n[1005];int bh(int a,int b){ if(a>=b) { return b; } else { return a; }}int main(){ int t; scanf("%d",&t); while(t--) { int flag=1; scanf("%d%d",&point,&line); for(int i=1; i<=point; i++) //这里的i=1 i<=point 不可以换成i=0 i<point { a[i]=i; } for(int i=0; i<line; i++) //输入的同时开始合并一些集合 { scanf("%d%d",&m[i],&n[i]); a[m[i]]=bh(a[m[i]],a[n[i]]); a[n[i]]=bh(a[m[i]],a[n[i]]); } for(int i=1; i<point; i++) //同上 不可以换 { if(a[i]!=a[i+1]) { flag=0; break; } } if(flag==0) { printf("NO\n"); } else { printf("YES\n"); } }}
这样一个判断是否为连通图的代码就来了
如果是 输出YES 否则NO
但是,刚开始没发现,后来dbug的时候发现了
这样判断连通图是有错误的
如
1
6 6
2 3
3 4
1 2
6 5
4 5
1 6
这组数据是不对的,因为我每一次合并两个集合时只是把这个集合的一个数拉过来
其余的并没有考虑 下面修改代码
下面直接贴上AC代码
#include<stdio.h>#include<string.h>int a[1005],d[1005],m[2005],n[2005];int min(int a,int b){ if(a>=b) { return b; } else { return a; }}int max(int a,int b){ if(a<=b) { return b; } else { return a; }}int main(){ int t; scanf("%d",&t); while(t--) { int point,line,x1,x2; int flag=1,num=0; scanf("%d%d",&point,&line); memset(d,0,sizeof(d)); memset(a,0,sizeof(a)); for(int i=1; i<=point; i++) //初始化 { a[i]=i; } for(int i=1; i<=line; i++) //输入的同时开始合并一些集合 { scanf("%d%d",&m[i],&n[i]); x1=max(a[m[i]],a[n[i]]); x2=min(a[m[i]],a[n[i]]); //printf("%d %d\n",x1,x2); for(int j=1;j<=point ;j++) { if(a[j]==x1) { a[j]=x2; } } d[m[i]]++; d[n[i]]++; /*for(int j=1;j<=point ;j++) { printf("%d ",a[j]); } printf("\n");*/ } for(int i=1; i<point; i++) //判断是否为连通图 { if(a[i]!=a[i+1]) { flag=0; break; } } for(int i=1; i<=point; i++) { if(d[i]%2==1) { num++; } } //printf("%d\n",num); if(flag==1&&point>1) { if(num==2||num==0) { printf("Yes\n"); } else { printf("No\n"); } } else if(point==1) { printf("Yes\n"); } else { printf("No\n"); } } return 0;}
错误之处就是修改时 要从头遍历一遍,如果符合修改条件 那就一块修改了,不能只修改一个
啊啊啊,这并查集我怎么觉得比递归还时间长
每输入一个就要从头便利一遍,是不是我方法错误的
下一篇文章我再来一遍这道题,并查集优化法
这篇比较惨
1 0
- nyoj 一笔画(并查集)
- nyoj--42--一笔画问题(并查集)
- NYOJ 42 一笔画问题 (DFS || 并查集)
- nyoj 一笔画问题(并查集,欧拉路)
- nyoj 一笔画(含并查集详解)
- NYOJ--42一笔画问题【并查集】
- NYOJ 42 一笔画问题 【欧拉图 + 并查集】
- 并查集 深搜 nyoj 42 一笔画问题
- nyoj-一笔画问题(欧拉图+并查集)
- nyoj 一笔画问题 【并查集+欧拉】
- NYOJ 42 一笔画问题(并查集+欧拉回路)
- NYOJ 42 一笔画问题(DFS||并查集+欧拉回路)
- NYOJ 42 一笔画问题(欧拉定理&&并查集)
- nyoj 42 一笔画问题(欧拉通路+dfs || 并查集)
- NYOJ-一笔画问题(并查集+欧拉回路)
- NYOJ 42 一笔画问题 (欧拉回路+并查集)
- 并查集-一笔画
- 欧拉路/回路_并查集 NYOJ 42 一笔画问题
- Runtime常用的几个应用场景
- MVC-model模型层
- java动态代理(JDK和cglib)
- 【opencv 官方教程】翻译6 Background Subtraction 和级联分类器
- 关于VC2013自动补全问题
- nyoj 一笔画(并查集)
- ZCMU—1595
- 宋仲基人气下滑?孔侑上位,衣品PK争上夺下
- Mavlink地面站编写之五—MP源码多线程读写框架分析
- unable to load dynamic library php_curl.dll
- mysql 如何查询插入数据表和数据结构
- Jdbc 查询oracle数据时间错误
- springMVC利用WebArgumentResolver为controller注入当前用户对象参数
- web弹层组件-layer封装的工具类