您的位置:首页 > 其它

NYOJ-42 一笔画问题

2014-11-08 10:19 274 查看
这个题可以有两种方式来解决, 一个是搜索来解决,另一个是用并查集,后者较前者来说要更快点

整个题的思路就是先判断整个图是否连通,然后再判断是否为欧拉图,即图中奇度顶点的个数是否为0或者2, 如果是0或者2的话就是欧拉图,就可以一笔画,所以,用搜索是来判断这个图是否连通,并查集也是,下面是代码的实现:

方法一(搜索):

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int n, q;
int a[1010][1010];
int vis[1010];
int degree[1010];
void dfs(int cur)
{
vis[cur] = 1;//如果能过去,就说明连通,标记为已经走过
for(int i = 1; i <= n; i++)
{
if(vis[i] == 0 && a[cur][i])
{
dfs(i);
}
}
}
int main()
{
int N;
scanf("%d", &N);
while(N--)
{

bool flag = true;
scanf("%d %d", &n, &q);
memset(a, 0, sizeof(a));
memset(vis, 0, sizeof(vis));
memset(degree, 0, sizeof(degree));
int t1, t2;
for(int i = 1; i <= q; i++)
{
scanf("%d %d", &t1, &t2);
a[t1][t2] = 1;
a[t2][t1] = 1;
++degree[t1];//统计节点的度数
++degree[t2];
}
dfs(1);
for(int i = 1; i <= n; i++)
{
if(vis[i] == 0)//如果图不连通
{
flag = false;
break;
}
}
int cnt = 0;
if(flag)
{
for(int i = 1; i <= n; i++)
{
if(degree[i] % 2 == 1)
cnt++;//统计奇度顶点的个数
}
if(cnt != 0 &&  cnt != 2)
flag = false;
}
if(flag)
printf("Yes\n");
else
printf("No\n");

}
return 0;
}


方法二(并查集):

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

const int N = 1010;
int father
, rank
;
int degree
;

int find(int n)
{
if (n != father
)
father
= find(father
);//路径压缩
return father
;
}
//合并函数
void unin(int x, int y)
{
int n = find(x);
int m = find(y);
if(n != m)
{
//rank用来保存当前点有多少个孩子了,始终孩子少的归顺孩子多的,合并根节点
if (rank
> rank[m])
{
father[m] = n;
rank
++;
}
else
{
father
= m;
rank[m]++;
}

}
}
int main()
{
int N;
scanf("%d", &N);
while(N--)
{
int p, q;
scanf("%d %d", &p, &q);
for(int i = 1; i <= p; i++)
father[i] = i;//初始化每个节点的父亲为他本身
memset(rank, 0, sizeof(rank));//清零
memset(degree, 0, sizeof(degree));//统计每个节点的度,
int a, b;
for(int i = 0; i < q; i++)
{
scanf("%d %d", &a, &b);
unin(a, b);
++degree[a];
++degree[b];
}
bool flag = true;
int t = father[1];//判断是否连通分量是否为1
for(int i = 2; i <= p; i++)
{
if (t != father[i])
{
flag = false;
break;
}
}

if(flag)
{
int cnt = 0;
for(int i = 1; i <= q; i++)
{
if(degree[i] % 2 == 1)//统计奇度定点的个数
cnt++;
}
if(cnt != 0 && cnt != 2)
flag = false;
}
if(flag)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: