zoukankan      html  css  js  c++  java
  • SGU 280.Trade centers(贪心)

    SGU 280.Trade centers 解题报告

    题意:

    n(<=30000)个城市,(n-1)条道路,求最少需要选择多少个城市建造市场,使得所有城市到任意一个市场的距离不大于k。


    Solution:

    比较好的贪心题。实现起来也有一定技巧。
    先以任意点为根,构造出一颗有根树。
    首先比较容易想到的是从叶子节点向上寻找,如果只有一个距离为k的点,就把它选上。但是有多个呢?
    于是思考更一般的做法,由于是树形结构,先考虑以x节点为根的子树。我们先假设f[x]代表离x节点向下的市场点的距离,这个值可以通过子树的f[]值得出。但是子树有多个f[]我们需要的是哪个呢?
    先来考虑x的儿子p,假设f[p]<=k,那么p已经被覆盖,并可能覆盖到x和它的父节点和它的兄弟子树。假设f[p]>k,那么p需要在x或它的父亲中建造市场,要么其实他已经被它的兄弟子树覆盖。这个可以通过判断$max(f[p])+min(f[p])+2$是否小于等于2*k+1来判断。
    如果x的子树全部被覆盖了,那么$f[x] = min(f[p])+1$,
    如果没有,$f[x]=max(f[p])+1$,并且如果f[x]=2*k+1那么让x成为关键点。即令$f[x]=0$。
    注意在根的时候,根节点无法向上,如果f[root]>k说明子树中有节点需要在根节点建造市场。
    根据定义叶子节点k应该满足f[k]=k+1。
    最后输出f[]为0的节点就行了。

    
    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    using namespace std;
    
    const int INF = 31111;
    
    vector<int> edge[INF], ans;
    int f[INF];
    int n, k, tol;
    int dfs ( int x , int fa )
    {
        int dmax = -INF, dmin = INF, s = 0;
        f[x] = k + 1;
        for ( int i = 0; i < edge[x].size(); ++i ) {
            int v = edge[x][i];
            if ( v == fa ) continue;
            ++s;
            dfs ( v , x );
            dmin = min ( f[v], dmin );
            dmax = max ( f[v], dmax );
        }
        if ( s ) {
            if ( dmin + dmax + 2 <= 2 * k + 1 ) f[x] = dmin + 1;
            else f[x] = dmax + 1;
        }
        if ( f[x] == 2 * k + 1 ) {
            f[x] = 0;
            ++tol;
        }
    }
    
    int main()
    {
        scanf ( "%d %d", &n, &k );
        for ( int i = 2, x, y; i <= n; ++i ) {
            scanf ( "%d %d", &x, &y );
            edge[x].push_back ( y );
            edge[y].push_back ( x );
        }
        dfs ( 1 , 0 );
        if ( f[1] > k ) ++tol, f[1] = 0;
        printf ( "%d
    ", tol );
        for ( int i = 1; i <= n; i++ )
            if ( f[i] == 0 ) printf ( "%d
    ", i );
    }
    /*
    14 3
    1 2
    1 3
    1 4
    2 5
    2 6
    3 7
    3 8
    4 9
    7 10
    7 11
    10 12
    11 13
    13 14
    
    answer:
    2
    1
    7
    */
    
    
  • 相关阅读:
    Java 将File转换为MultipartFile类型
    JAVA中实现根据文件路径下载文件
    Java中类似单元格之间的计算公式解析,如A1+B3-B4
    Java JPA通过hql语句查询数据
    mysql与oracle 表字段定义比较
    Java时间日期DateUtil
    fetch缓存问题
    Vue中watch的简单应用
    关于跨域和如何解决跨域问题的小结
    Google play 一直等待下载?解决方案如此简单!
  • 原文地址:https://www.cnblogs.com/keam37/p/4663456.html
Copyright © 2011-2022 走看看