无忧无虑
隔壁村李小花垂涎我已久,可是我是要做海贼王的男人,于是拒绝了李小花……

题目链接:http://codeforces.com/contest/573/problem/C
题目大意:在两行无限长的点列上面画n个点以及n-1条边使得构成一棵树,并且要求边都在同一平面上且除了节点处任意两条边之间没有公共交点。给定n和n-1条边的关系,问这棵树能否满足要求地画在这个两行平行点列上?

解题思路:我们假设这么k一棵树已经被画好在了这个两行平行点列上,我们在其中选择最左边地点和最右边的点,并且设连接最左边的点和最右边的点为主链,可以发现,在树所在地区域内,主链会将剩下的区域划分为零个或多个一行区域。

 

                   只有两种类型地地子树能够插入到主链中:Y字母(Y-letter)和链(Line)。
                                     这里说的Y字母指的是长得像Y字母这样地三叉结构。

                      Y字母可以有很长的腿(legs)但是它的中心区域只能有一条边。

如果所给的树能够表示成一条主链和若干插入其上地Y字母和链,那么这就是一棵合法的树。
首先,我们递归地从每一个叶子节点开始标记删除度数<=2的结点(标记该结点地状态为删除,而不是真正删除该结点,从而不影响接下来度数地计算),直到遇到某一个节点度数>2为止,对于最后这个节点(度数>2地节点),我们不删除它,而是标记该节点的legs值加1.
最后,对于所有没有被标记为删除的点,如果该点满足"度数-min(legs,2)>1"(degree-min(legs,2)>1)这一条件,他就是"主链上的点",否则,它就是"Y字母的起点"。
如果所有"主链上的点"的相邻的"主链上地点"地数目均<=2,则答案为"Yes",否则答案为"No"。
Java代码:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Wuyouwulv {
    private static final int maxn = 100010;
    private static ArrayList<Integer> g[];
    private static int[] legs = new int[maxn];
    private static int[] degree = new int[maxn];
    private static boolean[] del = new boolean[maxn];
    
    private static void dfs(int u, int pa) {
        int sz = g[u].size();
        if(sz > 2) {
            legs[u] ++;
            return;
        }
        del[u] = true;
        for(int v : g[u]) {
            if(v == pa) continue;
            dfs(v, u);
        }
    }
    
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while(in.hasNext()) {
            int n = in.nextInt();
            g = new ArrayList[n];
            for(int i=0;i<n;i++) g[i] = new ArrayList<Integer>();
            for(int i=1;i<n;i++) {
                int u , v;
                u = in.nextInt() - 1;
                v = in.nextInt() - 1;
                g[u].add(v);
                g[v].add(u);
                degree[u] ++;
                degree[v] ++;
            }
            for(int i=0;i<n;i++) {
                if(!del[i] && degree[i] == 1) {
                    dfs(i, -1);
                }
            }
            for(int u=0;u<n;u++) {
                if(!del[u] && degree[u] - Math.min(legs[u], 2) > 1) {
                    int cnt = 0;
                    for(int v : g[u]) {
                        if(!del[v] && degree[v] - Math.min(legs[v], 2) > 1) {
                            cnt ++;
                            if(cnt > 2) {
                                System.out.println("No");
                                return;
                            }
                        }
                    }
                }
            }
            System.out.println("Yes");
            return;
        }
    }
}
View Code

 

posted on 2015-10-10 21:19  wuyouwulv  阅读(276)  评论(0编辑  收藏  举报