#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include<algorithm> #include<vector> using namespace std; //判树条件:连通、边数=顶点数-1、入度不大于1 //多组分组输入且有结束条件: //while(1) // { // if(总结束条件) // { // break; // else if(分组结束条件) // { // 判断并输出结果; // 重置初始化; // } // else // { // 组内处理流程; // } //} //并查集 int father[10001];//存各节点对应根节点 void InitDisjointSet(int n) { //初始化,每个节点的根节点设为自己 for (int i = 1; i <= n; ++i) { father[i] = i; } } int FindDisjointSet(int u) { //寻找根节点 if (u == father[u]) { //如果自己就是根节点直接返回 return u; } else { //return FindDisjointSet(father[u]);原版,容易导致退化为链表 //改进:每次先更新当前节点的根再返回 father[u] = FindDisjointSet(father[u]);//递归访问上一级 return father[u]; } } void UnionDisjointSet(int u, int v) { //合并v所在的集合到u的根下面 int uroot = FindDisjointSet(u); int vroot = FindDisjointSet(v); father[vroot] = uroot; } int main() { int u, v; InitDisjointSet(10001); int edgeCount = 0; int vertexCount = 0; //vector默认填充0 vector<int>vertex(10001);//vertex[i]为0说明i未出现过 vector<int>inDegree(10001);//记录i的入度 bool isOK = true; int caseIdx = 1; while (1) { scanf("%d%d", &u, &v); if (u == -1 && v == -1) { break; } else if (u == 0 && v == 0) { //一个图的所有边已经记录完成了 //边等于顶点减一 if (vertexCount != edgeCount+1) { isOK = false; } //空树特例 if (vertexCount == 0 && edgeCount == 0) { isOK = true; } //输出结果 if (isOK == true) { printf("Case %d is a tree.\n", caseIdx); } else { printf("Case %d is not a tree.\n", caseIdx); } //重置代码 InitDisjointSet(10001); edgeCount = 0; vertexCount = 0; for (int i = 0; i < 10001; i++) { vertex[i] = 0; inDegree[i] = 0; } isOK = true; caseIdx++; } else { //加入新边 ++edgeCount; if (vertex[u] == 0) { vertex[u] = 1; ++vertexCount; } if (vertex[v] == 0) { vertex[v] = 1; ++vertexCount; } if (FindDisjointSet(u) == FindDisjointSet(v)) { isOK = false; } else { UnionDisjointSet(u, v); } ++inDegree[v]; if (inDegree[v] >= 2) { isOK = false; } } } return 0; }