hdu1325Is It A Tree?【并差集】

来源:互联网 发布:直播摄像头美颜软件 编辑:程序博客网 时间:2024/06/05 10:46
#include <iostream>using namespace std;//题意:和题目1272类似,判断给定的有向图是不是一颗树//思路:树的定义:或着是一颗空树,或者为一颗非空树,只有一个根节点,其他的节点构成了m(m > 0)个//         互不相交的有限集合,每一个集合本身又是一颗树//判断方法:1、或者为一颗空树//          2、对于一颗非空树,只有一个根节点,该节点的入度为0,其他的每一个定点的入度为1//          3、并且不能有环,即n个节点只能有n-1条边#define NSIZ 100010int parent[NSIZ];int myrank[NSIZ];int flag[NSIZ];int degree[NSIZ];void make_set(int n){int i;memset(flag, 0, sizeof(flag));memset(degree, 0, sizeof(degree));for(i = 1;i < n; ++i){parent[i] = i;myrank[i] = 1;}}int find_set(int x){if(x != parent[x]){parent[x] = find_set(parent[x]);}return parent[x];}void union_set(int x, int y){x = find_set(x), y = find_set(y);if(x != y){if(myrank[x] < myrank[y]){parent[x] = y;myrank[y] += myrank[x];}else{parent[y] = x;myrank[x] += myrank[y];}}}int main(){  int n, m;int i, t = 1, x, y, fx, fy;int minD,maxD;int isOK;while(scanf("%d %d", &x, &y) != EOF && x > 0 && y > 0){if(!x && !y){printf("Case %d is a tree.\n", t++);continue;}//initmake_set(NSIZ);isOK = 0;minD = min(x, y);maxD = max(x, y);do{minD = min(minD, min(x, y));maxD = max(maxD, max(x, y));flag[x] = 1;flag[y] = 1;fx = find_set(x);fy = find_set(y);degree[y]++;if(fx == fy){isOK = -1; //标志图中有环}else{if(degree[y] > 1) //非根节点入度必须为1{isOK = -1;}union_set(x, y);}}while(scanf("%d %d", &x, &y) != EOF && (x + y));//图中无环时,看看图是否是连同的,如果不是连同的则会有至少2个根节点if(!isOK){for(i = minD; i <= maxD; ++i){if(flag[i] && i == find_set(i)){isOK++;}}}if(isOK == 1){printf("Case %d is a tree.\n", t++);}else{printf("Case %d is not a tree.\n", t++);}}return 0;}