sgu280:Trade centers(贪心构造)

题目大意:

给定一棵n个结点的树,从中选出一个最小点集S,使得树中每一个点到点集的最小距离≤k。

分析:

根据贪心原则,每两个S中的点,尽量使得两个点之间的距离=2k+1,因为如果两个点距离≤2k+1,中间所有的点都是可以覆盖得到的。

设fi表示i到子树中某一个S中的点的距离。

如果i为叶子结点,fi=k+1,表示它只能由kth ancestor覆盖(看不懂请往下);

如果i有一个孩子j,那么fi=fj+1;

如果i有两个以上的孩子,那么从孩子中选一个最大的fmax,和最小的fmin。如果fmin+fmax≤2k+1,表示这棵子树中所有的点都可以被覆盖,fi=fmin+1,没必要再选根结点;如果fmin+fmax>2k+1,表示这棵子树中所有的点没有都被覆盖,那么这时fi=fmax+1。如果fi=2k+1,那么将这个点加入S中,fi置为0。

对于根节点,如果f1>k那么也要将其加入S中。

AC code:

#include <cstdio>
#include <vector>
#include <algorithm>
#define pb push_back
using namespace std;

const int MAXN = 30009;
const int INF = 0x3f3f3f3f;

int n, k;
int rank[MAXN];
bool is[MAXN];
vector<int> ans;

struct Ugraph
{
    int size;
    int head[MAXN];
    int to[MAXN<<1];
    int ne[MAXN<<1];
    Ugraph() {size = 1;}
    void add_edge(int u, int v)
    {
        to[size] = v, ne[size] = head[u], head[u] = size++;
        to[size] = u, ne[size] = head[v], head[v] = size++;
    }
}G;

void dfs(int x, int fa)
{
    int y, minr = INF, maxr = -INF, c = 0;
    for(int i = G.head[x]; i; i = G.ne[i])
    {
        y = G.to[i];
        if(y != fa)
        {
            dfs(y, x);
            minr = min(minr, rank[y]);
            maxr = max(maxr, rank[y]);
            c++;
        }
    }
    if(!c) rank[x] = k+1;
    else if(c == 1) rank[x] = minr+1;
    else
    {
        if(minr+maxr+2 <= 2*k+1) rank[x] = minr+1;
        else rank[x] = maxr+1;
    }
    if(rank[x] == 2*k+1) is[x] = true, rank[x] = 0;
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif

    scanf("%d%d", &n, &k);
    for(int i = 1; i < n; ++i)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        G.add_edge(u, v);
    }
    dfs(1, 0);
    for(int i = 1; i <= n; ++i)
        if(is[i] || (i == 1 && rank[i] > k))
            ans.pb(i);
    printf("%d\n", ans.size());
    for(int i = 0, sz = ans.size(); i < sz; ++i)
        printf("%d\n", ans[i]);

    #ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    #endif
    return 0;
}
时间: 2024-10-13 13:10:59

sgu280:Trade centers(贪心构造)的相关文章

【贪心专题】HDU 1009 FatMouse&#39; Trade (贪心选取)

链接:click here~~ 题意:老鼠准备了M磅猫食,准备拿这些猫食跟猫交换自己喜欢的食物.有N个房间,每个房间里面都有食物.你可以得到J[i]单位的食物,但你需要付出F[i]单位的的猫食. 计算M磅猫食可以获得最多食物的重量. [解题思路]贪心算法,求最优解.将J[i]/F[i]的值从大到小排列,每次取最大的,局部最优,达到全局最优,从而获得最大值. 代码: // 贪心策略,优先选择投资最大的房间,每选择一次,交换次数依次减少,最后的次数用于价值最小的 //注意精度转化:1.0*(int

HDU1009_FatMouse&amp;#39; Trade【贪心】【水题】

FatMouse' Trade Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 44470    Accepted Submission(s): 14872 Problem Description FatMouse prepared M pounds of cat food, ready to trade with the cats g

HDU1009:FatMouse&#39; Trade(初探贪心,wait)

FatMouse prepared M pounds of cat food, ready to trade with the cats guarding the warehouse containing his favorite food, JavaBean. The warehouse has N rooms. The i-th room contains Jii pounds of JavaBeans and requires Fii pounds of cat food. FatMous

HDU1009_FatMouse&#39; Trade【贪心】【水题】

FatMouse' Trade Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 44470    Accepted Submission(s): 14872 Problem Description FatMouse prepared M pounds of cat food, ready to trade with the cats g

HDU 1009 FatMouse&#39; Trade (贪心算法)

题意:就是老鼠要用猫粮换粮食,第i个房间一些东西,要用东西去换,可以不全换.问给定的猫粮最多能换多少粮食. 析:贪心算法.我们先算出来每个房间物品的平均价格是多少,肯定越低越好,并且如果能全换就全换,如果不能, 肯定是最后一次了,就把剩下全部换了,看看能换多少.求和. 代码如下: #include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <v

HDU1009 FatMouse&#39; Trade 【贪心】

FatMouse' Trade Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 42786    Accepted Submission(s): 14274 Problem Description FatMouse prepared M pounds of cat food, ready to trade with the cats g

HDU 1009.FatMouse&#39; Trade【贪心算法】【8月16】

FatMouse' Trade Problem Description FatMouse prepared M pounds of cat food, ready to trade with the cats guarding the warehouse containing his favorite food, JavaBean. The warehouse has N rooms. The i-th room contains J[i] pounds of JavaBeans and req

贪心+构造 Codeforces Round #277 (Div. 2) C. Palindrome Transformation

题目传送门 1 /* 2 贪心+构造:因为是对称的,可以全都左一半考虑,过程很简单,但是能想到就很难了 3 */ 4 /************************************************ 5 Author :Running_Time 6 Created Time :2015-8-3 9:14:02 7 File Name :B.cpp 8 *************************************************/ 9 10 #include

UVA 10821 - Constructing BST(贪心构造)

UVA 10821 - Constructing BST 题目链接 题意:有1 - n的数字,要构造一棵高度不超过h的BST,并且要字典序最小的,输出序列 思路:贪心构造,既然字典序最小,那么每个子树的根都要尽量小,那么也就是右子树尽量填满,按照这个策略去dfs构造即可 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int n, h; void dfs