• [Usaco2008 Jan]电话网络


     [Usaco2008 Jan]电话网络

    描述

    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计算一下,为了建立能覆盖到所有草地的通信系统,他最少要建多少座无线电通讯塔。

    输入

    第1行: 1个整数,N

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

    输出

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

    样例

    输入

    5
    1 3
    5 2
    4 3
    3 5
    输入说明:
    Farmer John的农场中有5块草地:草地1和草地3相邻,草地5和草地2、草地
    4和草地3,草地3和草地5也是如此。更形象一些,草地间的位置关系大体如下:
    (或是其他类似的形状)
    

    输出

    2
    输出说明:
    FJ可以选择在草地2和草地3,或是草地3和草地5上建通讯塔
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,head[1000001],tot,f[10001][3];
     4 //f[i][0] i被自己覆盖
     5 //f[i][1] i被儿子覆盖 
     6 //f[i][2] i被父亲覆盖
     7 //f[i][0]+=min(f[son][1],f[son][2],f[son][0]) 
     8 //f[i][1]=f[x][0]+sigma(min (f[son][0],f[son][1]) ) 
     9 //f[i][2]+=min(f[son][0],f[son][1])
    10 struct data {
    11     int to,nxt;
    12 } e[1000001];
    13 void add(int x,int y) {
    14     e[++tot].to=y;
    15     e[tot].nxt=head[x];
    16     head[x]=tot;
    17 }
    18 void dp(int x,int fa) {
    19     int special_son=0;
    20     f[x][0]=1;
    21     for(int i=head[x]; i; i=e[i].nxt) {
    22         int v=e[i].to;
    23         if(v==fa)
    24             continue;
    25         dp(v,x);
    26         f[x][2]+=min(f[v][0],f[v][1]);
    27         f[x][0]+=min(min(f[v][0],f[v][1]),f[v][2]);
    28         if(f[special_son][0]-min(f[special_son][0],f[special_son][1])>f[v][0]-min(f[v][1],f[v][0]))
    29             special_son=v;    
    30     }
    31     f[x][1]=f[special_son][0];
    32     for(int i=head[x];i;i=e[i].nxt){
    33         int v=e[i].to;
    34         if(v==fa||v==special_son)
    35             continue;
    36         f[x][1]+=min(f[v][1],f[v][0]);
    37     }
    38 }
    39 int main() {
    40     scanf("%d",&n);
    41     for(int i=1,x,y; i<n; i++) {
    42         scanf("%d%d",&x,&y);
    43         add(x,y);
    44         add(y,x);
    45     }
    46     f[0][0]=0x3f;
    47     dp(1,-1);
    48     printf("%d
    ",f[1][1]<f[1][0]?f[1][1]:f[1][0]);
    49     return 0;
    50 }
  • 相关阅读:
    第九天 how can I 坚持
    第八天 how can I 坚持
    第七天 how can I 坚持
    第六天 how can I 坚持
    第五天 how can I 坚持
    第四天 how can I 坚持
    第三天 how can I坚持
    第二天 how can I 坚持
    raw文件系统 分类: 生活百科 2013-11-09 14:12 448人阅读 评论(0) 收藏
    初次接触:DirectDraw 分类: VC++ DirectX 2013-11-09 11:16 950人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/sbwll/p/13399442.html
Copyright © 2020-2023  润新知