题目连接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1268
测试例:
一定在思考的时候考虑问题考虑得全面一些,注意几种特殊情况:
0 0 空树是一棵树(没考虑到)
1 1 0 0 不是树 不能自己指向自己(没考虑到)
1 2 1 2 0 0 不是树 重复不行
1 2 2 3 4 5 0 0不是树 森林不算是树(主要是注意自己)
1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 1 0 0 注意 一个节点在指向自己的父亲或祖先 都是错误的 即 9-->1 错
1 2 2 1 0 0 也是错误的
/* 1. 判断入读大于2, 说明有环不行 2. 判断入读为0的个数只能为1, 为0或大于1都不行, 有头节点且只能有一个 3. 空树也是树 */ #include "iostream" #include "cstring" using namespace std; int nodes[1024],ideg[1024]; //nodes存储节点, ideg存储其相应的度 int main(){ int node1,node2, count = 0; int num = 1; //测试例 int isT = 1; //是不是树, 先置为1 memset(nodes, 0, sizeof(nodes)); memset(ideg, -1, sizeof(ideg)); while(cin>> node1 >> node2 && ( node1 != -1 ) && ( node2 != -1 )){ if(node1 == node2 && node1 == 0){ //如果输入的两个数都是0, 进入判断是不是树 int zcount=0; //存储度为0的节点数 int i = 0; for(i = 1; i <= count;i++){ if(ideg[i] == 0) zcount++; if(ideg[i] > 1) isT = 0; } if(zcount != 1) isT = 0; if(isT || count == 0) // count == 0即空树也是树 cout<<"Case "<<num++<<" is a tree."<<endl; else cout<<"Case "<<num++<<" is not a tree."<<endl; //恢复数据 count = 0; isT = 1; memset(nodes, 0, sizeof(nodes)); memset(ideg, -1, sizeof(ideg)); } else { if(node1 == node2) //如果两个节点相等, 不是树 isT = 0; int i = 0,flag1 = 0,flage2 = 0; for(i = 1 ;i <= count; i++){ if(node1 == nodes[i]) //如果数组里有node1, 则不管, 因为它是父节点 flag1 = 1; if(node2 == nodes[i]){ //如果弄得有node2, 则他的入度加1 flage2 = 1; ideg[i]++; } } if(!flag1){ //如果没有node1, 则新增一个位置存储node1, 并将其入度置为0 nodes[++count] = node1; ideg[count] = 0; } if(flage2 == 0){ //如果没有node2, 则新增一个位置存储node2, 并将其入度置为1 nodes[++count] = node2; ideg[count] = 1; } } } return 0; }
2012-12-07
并查集
#include<iostream> #include <cstring> using namespace std; int pre[1024], flage, rank[1024]; int find(int x){ //num表示找到头所用的步数 if(pre[x] == x || pre[x] == -1){ return x; } return pre[x] = find(pre[x]); } void join(int x, int y){ int num_x = 0, num_y = 0; int temp_x = find(x); int temp_y = find(y); //当前入度为1,则不能再有指向它的了 if(rank[y] >= 1) flage = false; //两个父节点相同就会有环, 1 1 0 0类似这种情况也可以排除 else if(temp_x == temp_y){ flage = false; } else{ pre[temp_x] = temp_y; pre[temp_y] = -1; //temp_y为头结点 rank[temp_y]++; //temp_y的入度加1 } } int main(){ //初始化数据 int i,iCase = 0, x, y, count = 0; for(i = 0; i < 1024; i++) pre[i] = i; flage = true; memset(rank, 0, sizeof(rank)); while(cin>>x>>y){ if(x == -1 && y == -1) return 0; if(x == 0 && y == 0){ for(i = 0; i < 1024; i++){ if(pre[i] == -1) //头结点标志为父节点-1 count++; if(count > 1){ //头结点个数大于1 flage = false; break; } } //输出结果 if(flage == false) cout<<"Case "<<++iCase<<" is not a tree."<<endl; else cout<<"Case "<<++iCase<<" is a tree."<<endl; //恢复数据 flage = true; count = 0; for(i = 0; i < 1024; i++) pre[i] = i; memset(rank, 0, sizeof(rank)); } else if(flage) join(x, y); } return 0; }