首页 > 试题广场 >

Is It A Tree?

[编程题]Is It A Tree?
  • 热度指数:16955 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
A tree is a well-known data structure that is either empty (null, void, nothing) or is a set of one or more nodes connected by directed edges between nodes satisfying the following properties. There is exactly one node, called the root, to which no directed edges point. Every node except the root has exactly one edge pointing to it. There is a unique sequence of directed edges from the root to each node. For example, consider the illustrations below, in which nodes are represented by circles and edges are represented by lines with arrowheads. The first two of these are trees, but the last is not.
In this problem you will be given several descriptions of collections of nodes connected by directed edges. For each of these you are to determine if the collection satisfies the definition of a tree or not.

输入描述:
The input will consist of a sequence of descriptions (test cases) followed by a pair of negative integers. Each test case will consist of a sequence of edge descriptions followed by a pair of zeroes Each edge description will consist of a pair of integers; the first integer identifies the node from which the edge begins, and the second integer identifies the node to which the edge is directed. Node numbers will always be greater than zero and less than 10000.


输出描述:
For each test case display the line "Case k is a tree." or the line "Case k is not a tree.", where k corresponds to the test case number (they are sequentially numbered starting with 1).
示例1

输入

6 8  5 3  5 2  6 4
5 6  0 0

8 1  7 3  6 2  8 9  7 5
7 4  7 8  7 6  0 0

3 8  6 8  6 4
5 3  5 6  5 2  0 0
-1 -1

输出

Case 1 is a tree.
Case 2 is a tree.
Case 3 is not a tree.
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static int n = 10001;
    public static int[] father = new int[n];//存储每个节点的父节点
    public static boolean[] isNode = new boolean[n]; //记录对应位置是否有节点
    public static int[] inDegree = new int[n];

    public static void init(){
        //对每个节点进行初始化,最开始每个节点都是一个单独的树
        for (int i = 0; i < n; i++) {
            father[i] = -1; //初始时刻每个节点的父节点都标记为-1
            isNode[i] = false;
            inDegree[i] = 0;
        }
    }

    public static boolean isTree(){
        //通过判断在这个图中,除了根节点,每个节点是否只有一个入度,对于根节点,是否只有一个节点入度为0
        int numRoot = 0; //记录根节点的个数:入度为0
        int node = 0; //记录节点个数
        for (int i = 0; i < n; i++) {
            if(!isNode[i]) continue; //此处没有节点,则继续下一次循环
            node++;
            if(inDegree[i] > 1){
                //有节点入度大于1,说明不是树
                return false;
            }
            if(inDegree[i] == 0){
                //是根节点
                numRoot++;
            }
        }

        //空树也是树
        if(node == 0) return true;
        else { //不是空树
            //如果树中的根节点个数大于1,肯定不是树
            if(numRoot > 1) return false;
            //接下来的情况只有根节点的个数为0或1
            //如果树中没有根节点,则不是树
            return numRoot != 0;
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int i = 1;
        init();
        while(sc.hasNextInt()){
            int start = sc.nextInt();
            int end = sc.nextInt();
            if(start < 0 && end < 0) break;
            if(start == 0 && end == 0 && isTree()){
                System.out.printf("Case %d is a tree.\n", i);
                i++;
                init(); //判断完一个图,继续判断下一个图
            }else if(start == 0 && end == 0){
                System.out.printf("Case %d is not a tree.\n", i);
                i++;
                init();
            }else {
                father[end] = start;
                isNode[start] = true;
                isNode[end] = true;
                inDegree[end]++;
            }
        }
    }
}

终于通过了,在判断是否为一颗树的那个函数那里,先考虑什么样的情况不是树,最后剩余的所有情况就都是树了。根据树的性质,每颗树只有一个根节点,入度为0,其余节点入度都为1
编辑于 2024-03-16 17:11:18 回复(0)
test case为什么7 35不是树,96 33却是树?只过了13%的test case。。。。
帖个代码,说下思路,主要还是利用并查集的思想,但是并查集没法检测环,所以要加上检测环的函数
import java.util.*;
public class Main {
    // 判断是否有环
    public static boolean isCyclic(int[] nodes, int start) {    
        int parent = nodes[start];
        while (parent != -1 && nodes[parent] != -1) {
            if (parent == start)
                return true;
            parent = nodes[parent];
        }
        return false;
    }
    // 判断是否树
    public static void judge(int[] nodes, boolean isTree, int k) {
        int index = 0;
        for (; nodes[index] != -1; ++index) ;
        boolean hasCircle = isCyclic(nodes, index);
        if (!isTree || hasCircle) {
            System.out.println("Case " + k + " is not a tree.");
        } else {
            System.out.println("Case " + k + " is a tree.");
        }
    }
    public static void main(String[] args) {
        int k = 1;
        int[] nodes = new int[10001];
        // nodes保存的是父子节点,-1表示未访问
        for (int i = 0; i < nodes.length; ++i) {
            nodes[i] = -1;
        }
        
        boolean isTree = true;
        Scanner reader = new Scanner(System.in);
        while (reader.hasNext()) {
            String line = reader.nextLine();
            String[] number = line.split(" +");
            for (int i = 0; i < number.length - 1; i=i+2) {
                int j = i + 1;
                int from = Integer.valueOf(number[i]);
                int to = Integer.valueOf(number[j]);
                if (from + to == -2 || from + to == 0) {
                    break;
                } else {
                    // case 1: to指向自己
                    // case 2: to已赋值,并且不等于当前的from
                    // case 3: to和from重复赋值,相当于入度大于1
                    if (from == to || (nodes[to] != -1 && nodes[to] != from) || nodes[to] == from) {
                        isTree = false;
                    } else if (nodes[to] == -1) {
                        nodes[to] = from;
                    }
                }
            }
            judge(nodes, isTree, k);
            ++k;
            isTree = true;
        }
    }
}

发表于 2018-04-04 14:08:32 回复(0)
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;

/*
 *	QQ:	825580813(一起来敲代码)
 *	思路:
 *		1,首先判断是不是自己指向自己 --> not
 *		2,申请一个HashMap用来保存每个节点的父节点的个数
 *		3,当输入 start end 时,这时,新添加的就有,start的父节点增加 0 个, end 的父节点增加一个
 *		4,最后只需要判断是否有多个节点的父节点为 0 或者 某个节点的父节点 大于1 即可.
 */
public class Main {
	
	public static void main(String[] args) {
		
		Scanner sc = new Scanner(System.in);
		int time = 1;
		while (sc.hasNext()) {
			int start = sc.nextInt();
			int end = sc.nextInt();
			if (start == -1 && end == -1) {
				break;
			}
			HashMap<Integer, Integer> map = new HashMap<>();
			boolean isTree = true;
			while (start != 0 && end != 0) {
				if (start == end) {
					isTree = false;
				}
				if (map.containsKey(start)) {
					map.put(start, map.get(start) + 1);
				}
				else {
					map.put(start, 0);
				}
				if (map.containsKey(end)) {
					map.put(end, map.get(end) + 1);
				}
				else {
					map.put(end, 1);
				}
				start = sc.nextInt();
				end = sc.nextInt();
			}
			Set<Map.Entry<Integer, Integer>> set = map.entrySet();
			int nullParent = 0;
			for (Entry<Integer, Integer> entry : set) {
				if (nullParent > 1 || entry.getValue() > 1) {
					isTree = false;
					break;
				}
				if (entry.getValue() == 0) {
					nullParent++;
				}
			}
			if (isTree) {
				System.out.println("Case " + (time++) + " is a tree.");
			}
			else {
				System.out.println("Case " + (time++) + " is not a tree.");
			}
		}
		sc.close();
	}
	
}


发表于 2017-06-01 22:30:59 回复(1)