• USACO Cell Phone Network


    USACO Cell Phone Network

    洛谷传送门

    JDOJ传送门

    Description

    Farmer John has decided to give each of his cows a cell phone in
    hopes to encourage their social interaction. This, however, requires
    him to set up cell phone towers on his N (1 <= N <= 10,000) pastures
    (conveniently numbered 1..N) so they can all communicate.

    Exactly N-1 pairs of pastures are adjacent, and for any two pastures
    A and B (1 <= A <= N; 1 <= B <= N; A != B) there is a sequence of
    adjacent pastures such that A is the first pasture in the sequence
    and B is the last. Farmer John can only place cell phone towers in
    the pastures, and each tower has enough range to provide service
    to the pasture it is on and all pastures adjacent to the pasture
    with the cell tower.

    Help him determine the minimum number of towers he must install to
    provide cell phone service to each pasture.

    Input

    * Line 1: A single integer: N

    * Lines 2..N: Each line specifies a pair of adjacent pastures with two
    space-separated integers: A and B

    Output

    * Line 1: A single integer indicating the minimum number of towers to
    install

    Sample Input

    5 1 3 5 2 4 3 3 5

    Sample Output

    2

    HINT

    INPUT DETAILS:

    Farmer John has 5 pastures: pastures 1 and 3 are adjacent, as are pastures
    5 and 2, pastures 4 and 3, and pastures 3 and 5. Geometrically, the
    farm looks like this (or some similar configuration)

                   4  2
                   |  |
                1--3--5
    

    OUTPUT DETAILS:

    The towers can be placed at pastures 2 and 3 or pastures 3 and 5.


    题解:

    节点选择类树形DP。

    这类树形DP一般都设好几种互相有着关联的状态,依此相互转移。(啊,我又来瞎YY总结了)

    (%QYB以免被骂)

    所以按套路设状态:

    (dp[i][0/1/2])表示i根子树全被覆盖,且i被自己、父亲、儿子覆盖的最小个数。

    转移也比较好想:

    [dp[x][0]=summin(dp[son][0],dp[son][1],dp[son][2])\dp[x][1]=summin(dp[son][0],dp[son][2])\dp[x][2]=dp[Son][0]+summin(dp[son][0],dp[son][2]) ]

    重点说一下最后这种状态,注意大小写。根据我们的状态,如果这个点被儿子覆盖,那么必然有一个儿子是被选的。即得先选一个儿子覆盖自己,剩下的其他儿子再正常累加。

    那么,如何挑选出这个必须选的Son呢?

    很显然,想要保证(dp[x][2])最优,需要使得这个Son的选择也最优。那么如果当前的选择是最优的,肯定会满足:

    [dp[Son_1][0]+summin(dp[son][0],dp[son][2])<dp[Son_2][0]+summin(dp[son][0],dp[son][2]) ]

    把相同项目消去,即有:

    [dp[son][0]-min(dp[son][0],dp[son][2])>dp[y][0]-min(dp[y][0],dp[y][2]) ]

    然后就有代码:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=1e4+10;
    int n;
    int tot,to[maxn<<1],nxt[maxn<<1],head[maxn];
    int dp[maxn][3];
    //dp[i][0/1/2]表示i根子树全被覆盖,且i被自己、父亲、儿子覆盖的最小价值。
    void add(int x,int y)
    {
        to[++tot]=y;
        nxt[tot]=head[x];
        head[x]=tot;
    }
    void dfs(int x,int f)
    {
        int son=0;
        dp[x][0]=1;
        for(int i=head[x];i;i=nxt[i])
        {
            int y=to[i];
            if(y==f)
                continue;
            dfs(y,x);
            dp[x][0]+=min(min(dp[y][0],dp[y][1]),dp[y][2]);
            dp[x][1]+=min(dp[y][0],dp[y][2]);
            if(!son||dp[son][0]-min(dp[son][0],dp[son][2])>dp[y][0]-min(dp[y][0],dp[y][2]))
                son=y;
        }
        if(son)
            dp[x][2]=dp[son][0];
        else
            dp[x][2]=998244353;
        for(int i=head[x];i;i=nxt[i])
        {
            int y=to[i];
            if(y==f||y==son)
                continue;
            dp[x][2]+=min(dp[y][0],dp[y][2]);
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        dfs(1,0);
        printf("%d",min(dp[1][0],dp[1][2]));
        return 0;
    }
    
  • 相关阅读:
    Qt Creator 5.0 发布
    Qt编写可视化大屏电子看板系统19-横向柱状图
    Qt开发经验小技巧166-170
    Qt编写安防视频监控系统62-子模块6预置位
    Qt编写可视化大屏电子看板系统18-柱状分组图
    Qt编写安防视频监控系统61-子模块5设备控制
    如果对golang的gin框架中的handler做单元测试
    samba
    内存溢出
    动态规划面试题
  • 原文地址:https://www.cnblogs.com/fusiwei/p/13814785.html
Copyright © 2020-2023  润新知