HDU 1272:小希的迷宫
判断图连通且无环即可。并查集水题,图连通说明整个集合只有一个代表,
无环即插入的任何x,y。x,y不能属于同一集合。本题坑点,直接输入0 0
属于空图,也要输出Yes。
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
const int maxn =100004;
int n,m;
int fa[maxn],vis[maxn];
void initSet() {
for(int i = 1; i < maxn; i++) {
fa[i] = i;
}
}
int findSet(int x) {
int temp = x;
while(x!=fa[x]) {
x = fa[x];
}
while(temp!=fa[temp]) {
temp = fa[temp];
fa[temp] = x;
}
return x;
}
void unionSet(int x,int y) {
fa[x] = y;
}
int main() {
int x,y,fx,fy;
while(~scanf("%d%d",&x,&y)) {
if(x==-1 && y==-1) {
break;
}
if(x==0 && y==0) {
printf("Yes\n");
continue;
}
memset(vis,0,sizeof(vis));
initSet();
bool flag = true; //代表无环
vis[x] = 1;
vis[y] = 1;
fx = findSet(x);
fy = findSet(y);
if(fx==fy) {
flag = false;
}
else {
unionSet(fx,fy);
}
while(true) {
scanf("%d%d",&x,&y);
if(x==0 && y==0) break;
vis[x] = 1;
vis[y] = 1;
fx = findSet(x);
fy = findSet(y);
if(fx == fy){
flag = false;
}
else {
unionSet(fx,fy);
}
}
int cnt = 0;
for(int i = 1; i < maxn; i++) {
if(vis[i]==1) {
if(fa[i]==i) {
cnt++;
}
}
}
if(cnt==1 && flag) {
printf("Yes\n");
}
else {
printf("No\n");
}
}
return 0;
}
HDU 1235 Is It A Tree
一颗树不能有环,且连通块数为1,和上题相同,但是并查集不会考虑边的有向性,所以
需要多加判断是否存在一个点有多个父亲,这也是树这种数据结构所不允许的。
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
const int maxn =100005;
int n,m;
int fa[maxn],vis[maxn],in[maxn];
void initSet() {
for(int i = 1; i < maxn; i++) {
fa[i] = i;
}
}
int findSet(int x) {
int temp = x;
while(x!=fa[x]) {
x = fa[x];
}
while(temp!=fa[temp]) {
temp = fa[temp];
fa[temp] = x;
}
return x;
}
void unionSet(int x,int y) {
fa[y] = x;
}
int main() {
int x,y,fx,fy,t=0;
while(~scanf("%d%d",&x,&y)) {
if(x<0 && y<0) {
break;
}
if(x==0 && y==0) {
printf("Case %d is a tree.\n",++t);
continue;
}
memset(vis,0,sizeof(vis));
memset(in,0,sizeof(in));
initSet();
bool flag = true; //代表无环
vis[x] = 1;
vis[y] = 1;
in[y]++;
fx = findSet(x);
fy = findSet(y);
if(fx==fy) {
flag = false;
}
else {
unionSet(fx,fy);
}
while(true) {
scanf("%d%d",&x,&y);
if(x==0 && y==0) break;
vis[x] = 1;
vis[y] = 1;
in[y]++;
//一个点有两个父亲。
if(in[y]>1) {
flag = false;
}
fx = findSet(x);
fy = findSet(y);
if(fx == fy){
flag = false;
}
else {
unionSet(fx,fy);
}
}
int cnt = 0;
for(int i = 1; i < maxn; i++) {
if(vis[i]==1) {
if(fa[i]==i) {
cnt++;
}
}
}
if(cnt==1 && flag) {
printf("Case %d is a tree.\n",++t);
}
else {
printf("Case %d is not a tree.\n",++t);
}
}
return 0;
}