• BZOJ 1596: [Usaco2008 Jan]电话网络


    Description

    Farmer John决定为他的所有奶牛都配备手机,以此鼓励她们互相交流。不过,为此FJ必须在奶牛们居住的N(1 <= N <= 10,000)块草地中选一些建上无线电通讯塔,来保证任意两块草地间都存在手机信号。所有的N块草地按1..N 顺次编号。 所有草地中只有N-1对是相邻的,不过对任意两块草地A和B(1 <= A <= N; 1 <= B <= N; A != B),都可以找到一个以A开头以B结尾的草地序列,并且序列中相邻的编号所代表的草地相邻。无线电通讯塔只能建在草地上,一座塔的服务范围为它所在的那块草地,以及与那块草地相邻的所有草地。 请你帮FJ计算一下,为了建立能覆盖到所有草地的通信系统,他最少要建多少座无线电通讯塔。

    Input

    * 第1行: 1个整数,N

    * 第2..N行: 每行为2个用空格隔开的整数A、B,为两块相邻草地的编号

    Output

    * 第1行: 输出1个整数,即FJ最少建立无线电通讯塔的数目

    题解:

    定义。
    dp[i][0] = sum(min(dp[s][2],dp[s][1]))自己没被选,父节点被选中
    dp[i][1] = sum(min(dp[s][1],dp[s][2]))自己没被选,某儿子结点被选中
    dp[i][2] = sum(min(dp[s][0],dp[s][1],dp[s][2]))自己被选中
    求dp[i][1] 时需注意当所有的dp[s][1] < dp[s][2]时是不满足条件的。

    ans=min(dp[1][2],dp[1][1])

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
     
    //by zrt
    //problem:
    using namespace std;
    typedef long long LL;
    const int inf(0x3f3f3f3f);
    const double eps(1e-9);
    int n;
    int H[10005],X[20005],P[20005],tot;
    inline void add(int x,int y){
        P[++tot]=y;X[tot]=H[x];H[x]=tot;
    }
    int dp[10005][3];//0 not 1 yes
    
    void dfs(int x,int fa){
        dp[x][0]=0;
        dp[x][2]=1;
        dp[x][1]=0;
        int stot=0;
        bool flag=0;
        int minn=inf;
        for(int i=H[x];i;i=X[i]){
            if(fa!=P[i]){
                stot++;
                dfs(P[i],x);
                dp[x][2]+=min(dp[P[i]][0],min(dp[P[i]][1],dp[P[i]][2]));
                dp[x][0]+=min(dp[P[i]][2],dp[P[i]][1]);
                if(dp[P[i]][1]<dp[P[i]][2]){
                    dp[x][1]+=dp[P[i]][1];
                    if(minn>dp[P[i]][2]-dp[P[i]][1]){
                        minn=dp[P[i]][2]-dp[P[i]][1];
                    }
                }else {
                    flag=1;
                    dp[x][1]+=dp[P[i]][2];
                }
            }
        }
        if(stot==0){
            dp[x][1]=inf;
            return;
        }
        if(!flag){
            dp[x][1]+=minn;
        }
         
    }
    int main(){
        #ifdef LOCAL
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
        #endif
        scanf("%d",&n);
        for(int i=1,x,y;i<n;i++){
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        dfs(1,-1);
        printf("%d
    ",min(dp[1][2],dp[1][1]));
         
        return 0;
    }
  • 相关阅读:
    10-padding(内边距)
    09-盒模型
    07-css的继承性和层叠性
    Python之路【第09章】:Python模块和包的详细说明
    Python之路【第10章】:程序异常处理
    Python之路【第09章】:Python模块
    排序算法—冒泡排序算法
    算法总结
    递归函数与二分法
    练习题
  • 原文地址:https://www.cnblogs.com/zrts/p/bzoj1596.html
Copyright © 2020-2023  润新知