zoukankan      html  css  js  c++  java
  • Acdream 1015 Double Kings 搜索

    题意:有一个国王要把他的领土分给两个儿子,国王的领土是一棵树,N个结点,N-1条边把这些结点连起来,现在大小儿子要选择一个点作为他的首都,那么除首都分别是这两个儿子之外,其他的城市(结点)根据离谁近就归谁所有,如果一样远的话就归大儿子所有,现在假设两个人都采取最优策略,且大儿子先选,问大儿子最多能够得到多少城市?

    解法:如果大儿子选择了一个点P,那么这个小儿子选择的点一定在P点的某个子树(M)当中,且P的其他子树一定归大儿子所有,对于子树M,小儿子的最优策略显然是选择和P相邻的哪一个点,否则将损失更多的城市。那么最后的解法就是大儿子选择一定P,改点满足P的所有的子树中拥有最大结点数的子树最小。

    这题前面写了一个建立在双向边的dfs,后来发现是错误的,直接一次dfs,然后根据树的特性求出另外一边子树的个数即可。

    代码如下:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    
    struct Edge {
        int x, num, next;    
    }e[100005];
     
    int head[50005], idx, N, ans[50005];
    
    
    void addedge(int x, int y) {
        
        ++idx;
        e[idx].x = y, e[idx].num = 0;
        e[idx].next = head[x];
        head[x] = idx;
    }
    
    void dfs(int x, int f) {
        for (int i = head[x]; i != -1; i = e[i].next) {
            if (e[i].x != f) { // 如果遇到父节点就跳过  
                int v = e[i].x; 
                dfs(v, x);
                for (int j = head[v]; j != -1; j = e[j].next) {
                    if (e[j].x == x ){ continue; }
                    e[i].num += e[j].num;
                }
                e[i].num += 1;
                e[i^1].num = N - e[i].num;
            }
        } 
    }
    
    int main() {
        int x, y, ret;
        while (scanf("%d", &N) == 1) {
            idx = -1;
            ret = 0x7fffffff;
            memset(ans, 0, sizeof (ans));
            memset(head, 0xff, sizeof (head));
            for (int i = 1; i < N; ++i) {
                scanf("%d %d", &x, &y);
                addedge(x, y);
                addedge(y, x);
            }
            dfs(1, 0);
            for (int i = 1; i <= N; ++i) {
                for (int j = head[i]; j != -1; j = e[j].next) {
                    ans[i] = max(ans[i], e[j].num);
                }
                ret = min(ret, ans[i]);
            }
            printf("%d\n", N - ret);
         }
        return 0;    
    }
  • 相关阅读:
    kindle--瓦尔登湖
    8051
    c++
    Linux安装目录的选择
    Redis键值数据类型之散列类型
    Redis键值数据类型之字符串
    redis基本使用
    Ubuntu18.04 Redis安装
    Java String和int转换
    mysql获得自增主码的值
  • 原文地址:https://www.cnblogs.com/Lyush/p/2797677.html
Copyright © 2011-2022 走看看