题目描述:
输入任意组,两两连通的数据,最后以0,0结尾,判断所有的点是不是在一棵树上,并且不构成环。
这个题目应该注意的是:当输入0,0的时候应该是符合题意的,
当输入1,2 2,1 0,0 的时候是不符合题意的 应为构成了环
输入的不一定是从1开始 也不一定是连续的输入
当在hdu oj上提交总是WA的时候 把c++改为g++可能就a了
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; #define MAXN 100005 int pre[MAXN], vis[MAXN]; int jishu = 0; //代表合并了几次 int find(int n) { return n == pre[n] ? n : pre[n] = find(pre[n]); //递归式 查找当前节点的根节点 压缩路径 } int unionFri(int x,int y) //合并两个节点 使之有共同根节点 { int findX = find(x); //找到一个节点的根节点 int findY = find(y); if(findX != findY) //如果两个节点不是同一个根节点 合并 { pre[findX] = findY; jishu++; //每合并一次计数器就+1 与主函数的i等待比较 } return jishu; } int main() { int m,n; int i=0; int sum; for(int i=1;i<MAXN;i++) pre[i] = i; //初始化所有的根节点 memset(vis, 0 ,sizeof(vis)); while(scanf("%d%d",&m,&n)&&m!=-1&&n!=-1) { if (i == 0 && m == 0 && n == 0) //当输入0,0的时候就直接输出yes { puts("Yes"); continue; } if(m && n) //当不结束的时候 { i++; //主函数的计数器++ vis[m] = vis[n] = 1; //因为题目要求不一定连续 而且不一定从1开始 所以要标记 每个进来的节点 sum = unionFri(m,n); //合并两个节点 返回函数内部计数器 } else { if(i == sum) //如果函数内部的计数器和主函数的计数器相等 进行下面的判断 { int k =0, tmp = -1; //tmp用在后面保存 for(int j=1;j<MAXN;j++) //因为是不连续的 所以遍历所有 if (vis[j]) //如果是输入过的 进入 { if (tmp == -1) //当第一次进入的时候 找到第一个节点 tmp = find(j);//保存第一个节点的根节点 else if (tmp!=find(j)) //如果一个根节点和后面的根节点 又不是同一个的 计数器++ 并退出循环 { k++; break; } } if(k == 0) printf("Yes\n"); else printf("No\n"); } else printf("No\n"); //如果函数内部计数器 和主函数计数器不相等直接输出no i=0;//下面是对所有的东西进行初始化 jishu = 0; for(int i=1;i<MAXN;i++) pre[i] = i; memset(vis, 0 ,sizeof(vis)); } } return 0; }