zoukankan      html  css  js  c++  java
  • Uva LA 3902

    题目

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1903


    题意

    一棵树,根上有VOD站,要求任意叶节点到VOD站的距离不超过k,问最少建新VOD站数。

    思路

    1. 令vod[i]为节点i到VOD站的最短距离,  注意,这是在以i为根的树上有VOD站的情况下,如果没有,vod[i]就设为非法。

    依据树形DP的思路,如果在该节点(非叶节点)建站,vod[i]=0,否则 vod[i] = min(vod[child] + 1) for child in i.children.(此时注意不要统计没有VOD的子树的非法值)

    2. 令urge[i]为以i为根的树中有叶节点还没被满足的情况下,该节点能忍受VOD站在此树外的最远距离。注意如果所有叶节点都被满足了,urge[i]就设为非法。

    对于叶节点, urge[i] = k,对于非叶节点,urge[i] = min(urge[child] + 1] for child in i.children),(此时注意不要统计已经被满足的非法值)

    3. 如何判断这棵树的孩子们之间有没有相互满足?明显,如果urge[i]和vod[i]都存在,且urge[i] <= vod[i],则说明有兄弟相互满足的情况。

    4. 如果孩子们之间无法相互满足?如果urge[i] > 0,说明不紧迫,交给父亲树去办。如果urge[i] = 0,说明需要建新站。

    感想

    1. 注意边是无向边,因此边数是点数2倍!

    代码

    #include <algorithm>
    #include <cassert>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <map>
    #include <queue>
    #include <set>
    #include <tuple>
    #define LOCAL_DEBUG
    using namespace std;
    const int MAXN = 2e3 + 4;
    const int inf = 0x3ffffff;
    int n, k, s;
    int vod[MAXN];
    int urge[MAXN];
    int first[MAXN];
    int to[MAXN];
    int nxt[MAXN];
    int edgeNum;
    
    void addEdge(int f, int t) {
        nxt[edgeNum] = first[f];
        to[edgeNum] = t;
        first[f] = edgeNum++;
    }
    
    int dfs(int root, int fa) {
        if (nxt[first[root]] == -1) {
            urge[root] = k;
            vod[root] = inf;
            return 0;
        }
        int ans = 0;
        vod[root] = inf;
        urge[root] = inf;
        for (int p = first[root]; p != -1; p = nxt[p]) {
            int t = to[p];
            if (t == fa)continue;
            ans += dfs(t, root);
            if (vod[t] != inf) {
                vod[root] = min(vod[t] + 1, vod[root]);
            }
            if (urge[t] != inf) {
                urge[root] = min(urge[t] - 1, urge[root]);
            }
        }
        if (urge[root] != inf) {
            if (vod[root] != inf && vod[root] <= urge[root]) {
                urge[root] = inf;//satisfied
            }
            else if (urge[root] == 0 && root != s) {
                ans ++;
                vod[root] = 0;//set up a new one;
                urge[root] = inf;//satisfied
            }
        }
        return ans;
    }
    
    
    int main() {
    #ifdef LOCAL_DEBUG
        freopen("C:\Users\Iris\source\repos\ACM\ACM\input.txt", "r", stdin);
        //freopen("C:\Users\Iris\source\repos\ACM\ACM\output.txt", "w", stdout);
    #endif // LOCAL_DEBUG
        int T;
        scanf("%d", &T);
        for (int ti = 1; ti <= T; ti++) {
            memset(first, -1, sizeof first);
            edgeNum = 0;
            scanf("%d%d%d", &n, &s, &k);
            for (int i = 1; i < n; i++) {
                int f, t;
                scanf("%d%d", &f, &t);
                addEdge(f, t);
                addEdge(t, f);
            }
            int ans = dfs(s, -1);
            printf("%d
    ", ans);
            
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    java (取文本中间)字符串之间的文本
    Mysql数据库中text还是不够
    java读取网页内容
    controller to controller
    农历类
    java.lang.RuntimeException: com.google.inject.CreationException: Unable to create injector, see the following errors
    Java中List集合去除重复数据的方法
    idea启动tomcat的中文乱码问题
    idea局域网调试 can accept external connection不可勾选
    Mysql JDBC Url参数说明useUnicode=true&characterEncoding=UTF-8
  • 原文地址:https://www.cnblogs.com/xuesu/p/10391343.html
Copyright © 2011-2022 走看看