POJ3659 [usaco2008jan_gold]电话网络

校内OJ上的题,刚开始做的时候以为是道SB题10分钟就能搞完..

然后准备敲了才发现自己是个SB..

刚开始以为是个很裸的TreeDP,然后就只设了两个状态,但是怎么想怎么不对。复杂度好像要爆炸。改成左儿子右兄弟好像根本无法转移..

搜了搜题解,发现不用改成左儿子右兄弟,把两个状态改成三个状态就行了

$f[node][0]$ 在$node$节点的子树被覆盖且$node$被建立

$f[node][1]$ 在$node$节点的子树被覆盖且$node$未被建立

$f[node][2]$ 在$node$节点的子树均被覆盖但是$node$未被覆盖

然后对于$f[node][0]$和$f[node][2]$的状态转移方程可以很好的写出

$f[node][0]=\sum min(f[son][0],f[son][1],f[son][2])+1$

$f[node][2]=\sum f[son][1]$

$f[node][1]$相对来说有些麻烦,状态转移方程没那么好写。简单说一下就是$\sum min(f[son][1],f[son][0])$ 但是限制存在,是必须存在一个$son$的状态为$0$,所以需要在代码上加一些小处理。

需要注意的是,这里的状态必须为$0$的$son$并不是值最小的,而是和状态为$1$的比起来差值最大的。

代码实现上也存在一些细节,不多说。

 1 //OJ 1946
 2 //by Cydiater
 3 //2016.9.18
 4 #include <iostream>
 5 #include <cstdio>
 6 #include <cstring>
 7 #include <string>
 8 #include <algorithm>
 9 #include <queue>
10 #include <map>
11 #include <ctime>
12 #include <cmath>
13 #include <cstdlib>
14 #include <iomanip>
15 using namespace std;
16 #define ll long long
17 #define up(i,j,n)        for(int i=j;i<=n;i++)
18 #define down(i,j,n)        for(int i=j;i>=n;i--)
19 const int MAXN=1e6+5;;
20 const int oo=10005;
21 inline ll read(){
22     char ch=getchar();ll x=0,f=1;
23     while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
24     while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
25     return x*f;
26 }
27 ll N,f[MAXN][3],LINK[MAXN],len=0;
28 struct edge{
29     ll y,next;
30 }e[MAXN];
31 namespace solution{
32     inline void insert(int x,int y){e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;}
33     void init(){
34         N=read();
35         up(i,2,N){
36             int x=read(),y=read();
37             insert(x,y);
38             insert(y,x);
39         }
40     }
41     void TreeDP(int node,int fa){
42         f[node][0]=1;ll sum=0;
43         for(int i=LINK[node];i;i=e[i].next)if(e[i].y!=fa){
44             TreeDP(e[i].y,node);
45             f[node][2]+=f[e[i].y][1];
46             f[node][0]+=min(f[e[i].y][0],min(f[e[i].y][1],f[e[i].y][2]));
47             sum+=min(f[e[i].y][1],f[e[i].y][0]);
48         }
49         f[node][1]=oo;
50         for(int i=LINK[node];i;i=e[i].next)if(e[i].y!=fa){
51             f[node][1]=min(f[node][1],sum-min(f[e[i].y][1],f[e[i].y][0])+f[e[i].y][0]);
52         }
53     }
54     void output(){
55         cout<<min(f[1][0],f[1][1])<<endl;
56     }
57 }
58 int main(){
59     //freopen("input.in","r",stdin);
60     using namespace solution;
61     init();
62     TreeDP(1,0);
63     output();
64     return 0;
65 }

时间: 2024-10-27 04:57:24

POJ3659 [usaco2008jan_gold]电话网络的相关文章

codevs 3336 电话网络

3336 电话网络(二分+最短路) 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 黄金 Gold 题目描述 Description 由于地震使得连接汶川县城电话线全部损坏,假如你是负责将电话线接到震中汶川县城的负责人,汶川县城周围分布着N(1≤N≤1,000)根按 1..N 顺次编号的废弃的电话线杆,任意两根电话线杆间都没有电话线相连.一共P(1≤P≤10,000)对电话线杆间可以拉电话线,其余的由于地震使得无法被连接. 第i对电话线杆的两个端点分别为Ai,Bi,它们间的距离为

10.22~10.28一周经典题目整理(meeting,BZOJ4377,POJ3659)

meeting:给正n边形每个点染上黑色或者白色,问有多少个同色的等腰三角形. 以正五边形为例这里将最上面的点作为顶点,得到若干对相等的腰 ,注意到以最上面的点作为顶点的等腰三角形的个数,等于颜色相等且都为顶点颜色的对称点的个数. O(n^2)统计即可. PS:注意减去等边三角形的情况. 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <cstdlib> 5

1596: [Usaco2008 Jan]电话网络

1596: [Usaco2008 Jan]电话网络 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 601  Solved: 265[Submit][Status][Discuss] Description Farmer John决定为他的所有奶牛都配备手机,以此鼓励她们互相交流.不过,为此FJ必须在奶牛们居住的N(1 <= N <= 10,000)块草地中选一些建上无线电通讯塔,来保证任意两块草地间都存在手机信号.所有的N块草地按1..N 顺次

bzoj1596[Usaco2008 Jan]电话网络*

bzoj1596[Usaco2008 Jan]电话网络 题意: 在一棵树中选最少的点建塔,使得每个点都有塔或相邻点有塔.n≤10000. 题解: 贪心.dfs时对于每个当前点,在dfs完它的所有子节点后如果它以及它的儿子以及它的父亲没塔,则在它父亲处建塔. 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 #define inc(i

笨笨的电话网络

笨笨的电话网络 题目描述 多年以后,笨笨长大了,成为了电话线布置师.由于地震使得某市的电话线全部损坏,笨笨是负责接到震中市的负责人.该市周围分布着N(1<=N<=1000)根据1……n顺序编号的废弃的电话线杆,任意两根线杆之间没有电话线连接,一共有p(1<=p<=10000)对电话杆可以拉电话线.其他的由于地震使得无法连接. 第i对电线杆的两个端点分别是ai,bi,它们的距离为li(1<=li<=1000000).数据中每对(ai,bi)只出现一次.编号为1的电话杆已经

poj3659

/*poj3659树的最小支配集树状DPby xjy*/#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn=10000+100;struct node//链式前向星存图{    int to;    int next;};node edge[2*maxn];//因为无向,所以同一条边会存两次bo

电话网络

2.电话网络(phone.cpp/in/out) [题目描述] 由于地震使得连接汶川县城电话线全部损坏,假如你是负责将电话线接到震中汶川县城的负责人,汶川县 城周围分布着N(1≤N≤1,000)根按1..N 顺次编号的废弃的电话线杆,任意两根电话线杆间都没有电话线相 连.一共P(1≤P≤10,000)对电话线杆间可以拉电话线,其余的由于地震使得无法被连接. 第i 对电话线杆的两个端点分别为Ai,Bi,它们间的距离为Li(1≤Li≤1,000,000).数据中保证每对 (Ai,Bi)最多只出现1

【POJ3659】【USACO 2008 Jan Gold】 3.Cell Phone Network 树上最小支配集/贪心 两种做法

题意:求树上最小支配集 最小支配集:点集,即每个点可以"支配"到相邻点,求最少点数可以使所有点被支配. 图上的最小支配集是NP的,但是树上的可以DP做,是O(n)的. 暴力做就好了, f[i]表示此 点被选时的子树全支配的最小代价 g[i]表示其父亲节 点被选时的子树全支配的最小代价 h[i]表示其某子节 点被选时的子树全支配的最小代价 然后暴力转移. (v是子节点) f[x]=∑(min(f[v],min(g[v],h[v])))+1; g[x]=∑(min(f[v],h[v]));

POJ3659 Cell Phone Network(树上最小支配集:树型DP)

题目求一棵树的最小支配数. 支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻. 听说即使是二分图,最小支配集的求解也是还没多项式算法的.而树上求最小支配集树型DP就OK了. 树上的每个结点作为其子树的根可以有三个状态: 不属于支配集且还没被支配 不属于支配集但被其孩子支配 属于支配集 那么就是用dp[u][1\2\3]来表示动归的状态. 123转移该怎么转移就怎么转移..最后的结果就是min(dp[root][2],dp[root][3]). 要注意的是对于有些结点前2