nyist-42一笔画问题(欧拉通路) bfs||dfs||并查集
来源:互联网 发布:java多线程机制 编辑:程序博客网 时间:2024/04/30 22:02
- 描述
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
一笔画问题
时间限制:3000 ms | 内存限制:65535 KB
难度:4
注:此题和hdu1878一笔画问题 略有差别,本题中不要求回到源点,因此判断是否为欧拉同路时,有以下规律:
■⒈凡是由偶点组成的连通图,一定可以一笔画成。画时可以把任一偶点为起点,最后一定能以这个点为终点画完此图。
■⒉凡是只有两个奇点的连通图(其余都为偶点),一定可以一笔画成。画时必须把一个奇点为起点,另一个奇点终点。
■⒊其他情况的图都不能一笔画出。(有偶数个奇点除以二便可算出此图需几笔画成。)
根据欧拉总结的规律,我们只需要1、判断图是否联通2、判断点是奇点的个数,就可以了。
方法一,利用判断图中顶点度数是否全部为偶数 或者 存在两个奇数顶点,同时利用 并查集 判断所有顶点是否联通
#include<iostream>#include<cstring>#include<queue>#include<algorithm>#include<cstdlib>#include<cstdio>using namespace std;#define INF 0x3f3f3f3fconst int MaxV = 1005;int degree[MaxV],fa[MaxV];//分别表示顶点的度数和顶点的父节点,就是指向该点的顶点int N,M;int find(int x)//获取根节点{ return fa[x]==x?x:find(fa[x]);}int main(){ int n ; scanf("%d",&n); while(n--){ scanf("%d%d",&N,&M); memset(degree,0,sizeof(degree));//初始所有节点的度为0 for(int i = 1 ; i <= N; i++) fa[i] = i ; //所有结点的父节点都是自身 for(int i = 0 ; i < M ; i ++){ int u,v; scanf("%d%d",&u,&v); degree[u]++; //无向图,出度+1 degree[v]++; //入度+1 int x = find(fa[u]); int y = find(fa[v]); if(x!=y) //判断输入的两个顶点是否属于同一个树,即是否联通 fa[x]=y; //如果不联通,将其联通 } bool t1=false,t2=true ; int cnt = 0,cnt2=0 ; //cnt2用来记录奇数点个数 for(int i = 1 ; i <= N ; i++){ if(fa[i] == i ) //判断所有顶点是否联通,若联通说明每个顶点的父节点都为某个顶点 cnt++; //也就是说所有顶点中只有一个顶点与父节点相同 if(degree[i]&1){ //判断每个顶点的度数是否为奇数,一旦是,则证明不是欧拉图 cnt2++; if(cnt2>=3)break; } } if(cnt2!=2) //只有当图中仅有2个奇数点,才为欧拉图 t2 = false ; if (cnt == 1) t1= true; if(t1 && t2 )printf("Yes\n");//两个条件同时成立说明为欧拉图 else printf("No\n"); }return 0;}
方法二:
dfs:通过vector容器建立图的邻接表,从某个顶点开始搜索看是否能把其他所有顶点遍历(即是否全部联通),同时可用
vec.size()判断顶点的度数
#include<iostream>#include<cstring>#include<queue>#include<vector>#include<algorithm>#include<cstdlib>#include<cstdio>using namespace std;#define INF 0x3f3f3f3fconst int MaxV = 1001;int vis[MaxV],N,M; // N为顶点数,M为边数vector<int>vec[MaxV];void dfs(int i ){ vis[i] = 1; //将传进的源顶点(起点)标记1,表示已访问 vector<int>::iterator it; for(it= vec[i].begin() ; it != vec[i].end() ;it++)//邻点接表深搜每个顶点的连接 if(vis[*it] == 0 ) //如果该点并未被访问过 dfs(*it); //接着搜}int main(){ int n; cin>>n; while(n--){ memset(vis,0,sizeof(vis)); cin>>N>>M; for(int i = 1 ; i <= N ; i++) vec[i].clear(); for(int i = 0 ; i < M ; i++){ //邻接表 int u,v; cin>>u>>v; vec[u].push_back(v); vec[v].push_back(u); } //判断是否为欧拉通路 dfs(1); int cnt = 0 ;//cnt记录未被访问过的顶点,即判断图是否联通 int cnt2 = 0 ;//cnt2记录顶点度数为奇数的个数 for(int i = 1 ; i <= N; i++){ if(!vis[i]) //判断该顶点是否被访问过,若没说图没有全部联通 cnt ++; if(vec[i].size()&1) cnt2++; } if((cnt2 ==2 || cnt2== 0 ) && !cnt) cout<<"Yes"<<endl; else cout<<"No"<<endl; }return 0;}
方法三:
dbs:通过队列对图中某个顶点进行广度搜索。将与该点相连的其他任何点(边)都加入队列中,然后该点出列,并记录出列过点的总个数是否等于总顶点数(是否联通)。判断其他点与该点是否连接时可记录该点的度,便于决定是否是同路
#include<iostream>#include<cstring>#include<queue>#include<vector>#include<algorithm>#include<cstdlib>#include<cstdio>using namespace std;#define INF 0x3f3f3f3fconst int MaxV = 1001;int vis[MaxV],N,M; // N为顶点数,M为边数;int map[MaxV][MaxV];int odd,cnt;void bfs(){ int t,num; queue<int>s; s.push(1); /*从1开始*/ vis[1]=1; /*标记已访问该点*/ while(!s.empty()) /*队列非空*/ { t=s.front(); //取队列首元素 s.pop(); //出列 cnt++; //记录连接过的顶点个数 num=0; //记录奇数点的个数 for(int i = 1 ; i <= N ; i++){ if(map[t][i]!=0) {/*判断出列的和其他点之间是否有连线*/ if(vis[i]==0) { /*i点还未访问*/ s.push(i); vis[i]=1; } num++;//有连线说明度+1 } } if(num%2==1)//若度为奇数,记录加1 odd++; }}int main(){ int n; scanf("%d",&n);/*m组数据*/ while(n--) { odd=cnt=0; memset(vis,0,sizeof(vis)); /*初始化都没有访问*/ memset(map,0,sizeof(map));/*初始化都没有连线*/ cin>>N>>M; int u,v; for(int i = 0 ; i < M ; i++){ scanf("%d%d",&u,&v); map[v][u]=1; map[u][v]=1; /*建立图表*/ } bfs(); if((N==cnt)&&((odd==0)||(odd==2))) //图连通且有两个奇数点或没有奇数点 printf("Yes\n"); else printf("No\n"); } return 0;}
0 0
- nyist-42一笔画问题(欧拉通路) bfs||dfs||并查集
- nyoj 42 一笔画问题(欧拉通路+dfs || 并查集)
- nyist 42 一笔画问题(欧拉回路+并查集)
- nyist 42一笔画(欧拉通路)
- 一笔画问题 南阳oj42 【并查集+欧拉通路的判断】
- nyist 42一笔画问题(并查集+欧拉图)
- NYOJ 42 一笔画问题(DFS||并查集+欧拉回路)
- 一笔画问题(欧拉通路)
- 一笔画问题(欧拉通路)
- NYOJ42 一笔画问题 【欧拉回路】+【并查集】
- nyoj 一笔画问题 【并查集+欧拉】
- NYOJ 42 一笔画问题 (DFS || 并查集)
- 南阳42 一笔画问题(欧拉回路+并查集)
- NYOJ 题目42 一笔画问题 (欧拉连通图+并查集)
- NYOJ 42 一笔画问题(并查集+欧拉回路)
- NYOJ 42 一笔画问题(欧拉定理&&并查集)
- NYOJ 42 一笔画问题 (欧拉回路+并查集)
- NYOJ 一笔画问题(判断存在欧拉通路)
- Hibernate 懒加载lazy
- Maven中dependencyManagement的一点点说明
- 创建Android模拟器时提示"No system images installed for this target"的问题
- swift3新路程(4)数组和字典(array/dictionary)
- 【JZOJ4786】【NOIP2016提高A组模拟9.17】小a的强迫症
- nyist-42一笔画问题(欧拉通路) bfs||dfs||并查集
- 51nod1685 第K大区间2
- Yii2一些方法技巧小记
- php生成数据字典
- 图像处理中的一阶偏导数和二阶偏导数
- Android通知 ---- Notification
- Linux下curses库的安装和函数的使用
- 操作系统总结二
- 使用Spring Boot来加速Java web项目的开发