Nyoj42 一笔画问题 (欧拉道路)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nyoj42 一笔画问题 (欧拉道路)相关的知识,希望对你有一定的参考价值。
http://acm.nyist.net/JudgeOnline/problem.php?pid=42题目链接
-
#include <cstdio>
-
#include <cstring>
-
#define CLR(arr) memset(arr,0,sizeof(arr))
-
#define P 1001
-
int G[P],fa[P];
-
int find(int x){return x==fa[x]?x:x=find(fa[x]);}
-
int main()
-
{
-
int n,a,b,f,p,q;
-
scanf("%d",&n);
-
while(n--){
-
f=1;
-
scanf("%d%d",&p,&q);
-
for(int i=1;i<=p;i++)fa[i]=i;
-
while(q--){
-
scanf("%d%d",&a,&b);
-
G[a]++;//读取出入度
-
G[b]++;
-
fa[a]=find(b);
-
}
-
fa[a]=find(a);
-
for(int i=1;i<=p;i++)if((fa[i]=find(i))!=fa[a]){//判断各点是否在同一集合中
-
f=0;
-
break;
-
}
-
int sum=0;
-
if(f)//若已判断图为不连通,则不判断出入度
-
for(int i=1;i<=p;i++)if(G[i]%2){//判断出入度和是否为奇数
-
sum++;
-
if(sum>2){//出入度和为奇数,则不可能为欧拉道路
-
f=0;
-
break;
-
}
-
}
-
puts(f?"Yes\n":"No\n");
-
CLR(G);
-
}
-
return 0;
-
}
一笔画,儿时经常玩的游戏,后来才知道,那叫欧拉道路,这题本质就是对欧拉道路的判断,根据已有定理,可形成欧拉道路的图中任意点的出入度和为奇数的个数不可以超过2个,因为有出必有入,这一点很容易编程实现,但上面的定理是基于图连通的情况下,因此我们还需要判断图的连通性,因为不想无脑dfs或bfs,于是上网查找更高效的图连通性判断算法,发现有所谓的传递闭包,想起白书里有,就翻了一天书,发作了两天鼻炎,最后发现这种方法是基于floyd算法实现的,时间复杂度是O(n3),还是不满意,就想用并查集实现,发现果然可行,但用了整整4ms,排行最高的只用了0ms,我想知道用 了什么方法,结果也是利用了并查集,而且方法更聪明(改到极致。。),这里也贴一下。(这算不算侵权。。。),并查集真是我见过最好用的数据结构,简单,代码少,应用性强。
-
#include<stdio.h>
-
#include<string.h>
-
int father[1002];
-
int Find(int x)
-
{
-
if(father[x]==-1) return x;
-
return father[x]=Find(father[x]);
-
}
-
int main()
-
{
-
int n,m,T,i,in[1002],a,b,sum,f;
-
scanf("%d",&T);
-
while(T--)
-
{
-
memset(in,0,sizeof(in));
-
memset(father,-1,sizeof(father));
-
scanf("%d%d",&n,&m);
-
for(i=0,sum=0;i<m;i++)
-
{
-
scanf("%d%d",&a,&b);
-
++in[a]; ++in[b];
-
a=Find(a); b=Find(b);
-
if(a!=b) { father[a]=b; sum++; }
-
}
-
if(sum<n-1) { printf("No\n"); continue; }
-
for(i=1,f=0;i<=n;i++)
-
if(in[i]%2) { f++; if(f>2) break; }
-
if(f==0||f==2) printf("Yes\n");
-
else printf("No\n");
-
}
-
}
以上是关于Nyoj42 一笔画问题 (欧拉道路)的主要内容,如果未能解决你的问题,请参考以下文章