zoukankan      html  css  js  c++  java
  • USACO2008 Jan 电话网络

    Time Limit: 10 Sec Memory Limit: 162 MB

    Description

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

    Input

    (1)行: (1)个整数,(N)

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

    Output

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

    Sample Input

    5
    1 3
    5 2
    4 3
    3 5
    

    输入说明:

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

    Sample Output

    2
    

    输出说明:

    FJ可以选择在草地(2)和草地(3),或是草地(3)和草地(5)上建通讯塔。

    Source

    Gold

    Solution

    一眼的树形DP。非常像JSOI2018潜入行动对不对,不过那道题是计数题,而且操作方式也有点区别。但是思想还是类似的。

    我们仿照那个设一下(dp[i][2][2])分别表示(i)这个点,有没有安装,有没有被覆盖。然后我们发现(dp[i][1][1])是个废状态,安装了就一定会被覆盖。

    因此我们减少一下:

    (dp[i][0])(i)这个点没有安装信号塔,也没有其子节点安装的覆盖

    (dp[i][1])(i)这个点没有安装信号塔,但是被其子节点安装的覆盖

    (dp[i][2])(i)这个点安装了信号塔

    显然(dp[i][2])(dp[i][0])随便转移:

    [dp[i][2]=sum limits_{v ext{是}i ext{的子节点}}^{} min{dp[v][0],dp[v][1],dp[v][2]} ]

    [dp[i][0]=sum limits_{v ext{是}i ext{的子节点}}^{} dp[v][1] ]

    (dp[i][1])就复杂一点了。(dp[i][1])成立的条件是子节点至少要有一个点安装了信号塔。

    所以我们统计一个(是的子节点sum=sum limits_{v ext{是}i ext{的子节点}}^{} min{dp[v][2],dp[v][1]})

    然后(是的子节点dp[i][2]=min limits_{v ext{是}i ext{的子节点}}^{} sum-min{dp[v][2],dp[v][1]}+dp[v][2])

    然后就可以愉快地A题了。

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    #define lowbit(x) ((x)&(-(x)))
    #define REP(i,a,n) for(register int i=(a);i<=(n);++i)
    #define PER(i,a,n) for(register int i=(a);i>=(n);--i)
    #define FEC(i,x) for(register int i=head[x];i;i=g[i].ne)
    #define dbg(...) fprintf(stderr,__VA_ARGS__)
    namespace io{
    	const int SIZE=(1<<21)+1;char ibuf[SIZE],*iS,*iT,obuf[SIZE],*oS=obuf,*oT=oS+SIZE-1,c,qu[55];int f,qr;
    	#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),(iS==iT?EOF:*iS++)):*iS++)
    	inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
    	inline void putc(char x){*oS++=x;if(oS==oT)flush();}
    	template<class I>inline void read(I &x){for(f=1,c=gc();c<'0'||c>'9';c=gc())if(c=='-')f=-1;for(x=0;c<='9'&&c>='0';c=gc())x=x*10+(c&15);x*=f;}
    	template<class I>inline void write(I x){if(!x)putc('0');if(x<0)putc('-'),x=-x;while(x)qu[++qr]=x%10+'0',x/=10;while(qr)putc(qu[qr--]);}
    	struct Flusher_{~Flusher_(){flush();}}io_flusher_;
    }//orz laofudasuan
    using io::read;using io::putc;using io::write;
    typedef long long ll;typedef unsigned long long ull;
    template<typename A,typename B>inline bool SMAX(A&x,const B&y){return x<y?x=y,1:0;}
    template<typename A,typename B>inline bool SMIN(A&x,const B&y){return y<x?x=y,1:0;}
    
    const int N=10000+7,INF=0x3f3f3f3f;
    int n,x,y,dp[N][3];
    struct Edge{int to,ne;}g[N<<1];int head[N],tot;
    inline void Addedge(int x,int y){g[++tot].to=y;g[tot].ne=head[x];head[x]=tot;}
    
    inline void DFS(int x,int fa=0){
    	int sum=0;dp[x][0]=0;dp[x][2]=1;dp[x][1]=INF;
    	for(register int i=head[x];i;i=g[i].ne){
    		int y=g[i].to;if(y==fa)continue;DFS(y,x);
    		dp[x][0]+=dp[y][1];SMIN(dp[x][0],INF);
    		dp[x][2]+=min(dp[y][0],min(dp[y][1],dp[y][2]));SMIN(dp[x][2],INF);
    		sum+=min(dp[y][1],dp[y][2]);
    	}
    	for(register int i=head[x];i;i=g[i].ne)if(g[i].to!=fa)SMIN(dp[x][1],sum-min(dp[g[i].to][1],dp[g[i].to][2])+dp[g[i].to][2]);
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("BZOJ1596.in","r",stdin);freopen("BZOJ1596.out","w",stdout);
    #endif
    	read(n);for(register int i=1;i<n;++i)read(x),read(y),Addedge(x,y),Addedge(y,x);
    	DFS(1,0);write(min(dp[1][1],dp[1][2])),putc('
    ');//错误笔记:手残把dp[1][2]打成dp[2][1] 
    }
    
  • 相关阅读:
    使用element-ui组件el-table时需要修改某一行样式(包含解决样式无效的问题)或某一列的样式
    面试题:线程A打印1-10数字,打印到第5个数字时,通知线程B
    面试题:不使用数学库求平方根
    Springboot2.x集成Redis集群模式
    Springboot2.x集成Redis哨兵模式
    Springboot2.x集成单节点Redis
    基本算法:冒泡排序算法
    Redis进阶:Redis的哨兵模式搭建
    Redis进阶:Redis的主从复制机制
    Redis的消息订阅及发布及事务机制
  • 原文地址:https://www.cnblogs.com/hankeke/p/BZOJ1596.html
Copyright © 2011-2022 走看看