链接地址http://acm.hdu.edu.cn/showproblem.php?pid=1325,评判结果:
Accepted | 1325 | 15MS | 232K | 2218 B | C++ |
本人的代码效率并不高,是用原始并差集的思想建了一棵树,不当之处请指教,好了废话少说,上代码:
//1:遍历数组parent,如果有小于-1且只有一个小于-1的点,就为这棵树的根节点 //2:防止出现3指向8,6指向8这种有两个parent指向同一个子节点的方法是每次更新parent之前判断是否该节点已经有一个父亲,即当parent[i]==-1的时候更新父节点 //3:防止出现环的情况,比如 // 1 2 // 2 3 // 3 1 // 的输入情况,为一个环,则数组中最后一个将会观察1是否为-1,若不是-1,切小于-1,则该点之前必为根节点,也即出现了环,不是树 #include<iostream> using namespace std; #define M 100 int parent[M]; bool isTree; int num = 1; int find(int x) find操作必须采用不要路径压缩的办法,这样可以建立一棵树,每个都指向他的父节点 { ///每次要用的find if(parent[x]<=-1) return x; else find(parent[x]); } void _union(int par,int child) { if(parent[child]>-1) ///第二条,说明该孩子已经有父节点 { isTree = false; return; } int root = find(par); 因为只是在根节点处更新树的大小,孩子始终是孩子,没有其他的根节点 if(root==child) 第三条,因为3的root节点是1,而3的child也是1,即判断root==child即可判断第三条 { isTree = false; return; } parent[root]--;/加入树中 parent[child] = par; } int main() { int par,child; int myMin,myMax; myMin = 0x7fffffff; myMax = 0; memset(parent,-1,sizeof(parent)); isTree = true; while(scanf("%d%d",&par,&child)) { if(par<0 && child<0) break; else if(par == 0 && child ==0) { int root = 0;代表root的数目 for(int i=myMin;i<=myMax;i++) { if(parent[i]<-1) root++; if(root>1) isTree = false; } //判断第一条,根节点数目 if(isTree) { printf("Case %d is a tree.\n",num++); memset(parent,-1,sizeof(parent)); myMin = 0x7fffffff; myMax = 0; continue; } else{ printf("Case %d is not a tree.\n",num++); memset(parent,-1,sizeof(parent)); isTree = true; myMin = 0x7fffffff; myMax = 0; continue; } } else{ if(par>child) { if(par>myMax) myMax = par; if(child<myMin) myMin = child; } else{ if(par<myMin) myMin = par; if(child>myMax) myMax = child; } /找到范围 _union(par,child); } } return 0; }