BZOJ 1596: [Usaco2008 Jan]电话网络 树形dp||贪心
2017-10-18 20:02
483 查看
1596: [Usaco2008 Jan]电话网络
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1100 Solved: 513
[Submit][Status][Discuss]
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最少建立无线电通讯塔的数目Sample Input
51 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上建通讯塔。
HINT
Source
Gold题解:
1。
之前想成2种状态了,后来发现父亲也可以染。。
dp[i][0]表示以i为根的子树的最小值,且i被它的儿子染。
dp[i][1]表示以i为根的子树的最小值,且选择i。
dp[i][2]表示以i为根的子树的最小值,且i被父亲染。(不能被儿子染)
然后就树上瞎搞。
#include<bits/stdc++.h> using namespace std; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} return x*f; } const int N = 10000 + 10; const int inf = 233333; int n; int dp [3]; struct node{ int pre,v; }e[N<<1]; int num=0,head ; void addedge(int from,int to){ e[++num].pre=head[from],head[from]=num; e[num].v=to; } void dfs(int u,int f){ dp[u][0]=inf,dp[u][1]=1; int sum=0; for(int i=head[u];i;i=e[i].pre){ int v=e[i].v; if(v==f) continue; dfs(v,u); dp[u][1]+=min(dp[v][0],min(dp[v][1],dp[v][2])); dp[u][2]+=dp[v][0]; sum+=min(dp[v][0],dp[v][1]); } for(int i=head[u];i;i=e[i].pre){ int v=e[i].v; if(v==f) continue; dp[u][0]=min(dp[u][0],sum+dp[v][1]-min(dp[v][0],dp[v][1])); } } int main(){ n=read(); for(int i=1;i<n;++i){ int u=read(),v=read(); addedge(u,v);addedge(v,u); } dfs(1,0); printf("%d",min(dp[1][0],dp[1][1])); return 0; }
2.贪心。
依旧dfs,每次找到一个点如果它的父亲和它自己和它的兄弟都没有被覆盖到,就把它的父亲覆盖。
其实正确性我不是很会证明……但是感性理解一下,这样每次选择的都是尽可能大的一个范围,所以会很优。
#include<bits/stdc++.h> using namespace std; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();} return x*f; } const int N = 10000 + 10; int n; int dp [3]; struct node{ int pre,v; }e[N<<1]; int num=0,head ; void addedge(int from,int to){ e[++num].pre=head[from],head[from]=num; e[num].v=to; } int ans=0,vis ; void dfs(int u,int f){ bool flag=true; for(int i=head[u];i;i=e[i].pre){ int v=e[i].v; if(v==f) continue; dfs(v,u); if(vis[v]) flag=false; } if(flag&&!vis[u]&&!vis[f]) vis[f]=true,++ans; } int main(){ memset(vis,0,sizeof(vis)); n=read(); for(int i=1;i<n;++i){ int u=read(),v=read(); addedge(u,v);addedge(v,u); } dfs(1,0); printf("%d\n",ans); return 0; }
相关文章推荐
- [BZOJ1596][Usaco2008 Jan]电话网络(贪心||树形dp)
- [BZOJ1596] [Usaco2008 Jan]电话网络(树形DP || 贪心)
- 【树形DP】BZOJ1596-[Usaco2008 Jan]电话网络
- BZOJ1596 [Usaco2008 Jan]电话网络 【树形dp】
- 【bzoj1596】[Usaco2008 Jan]电话网络 树形dp
- [BZOJ1596][Usaco2008 Jan]电话网络(树形dp)
- 【BZOJ】1596: [Usaco2008 Jan]电话网络(树形dp+特殊的技巧)
- [Usaco2008 Jan]电话网络 贪心 or 树形DP
- bzoj 1596: [Usaco2008 Jan]电话网络【贪心】
- BZOJ1596: [Usaco2008 Jan]电话网络 树形DP
- BZOJ 1596: [Usaco2008 Jan]电话网络
- [BZOJ1596] [Usaco2008 Jan]电话网络
- 【BZOJ】1596: [Usaco2008 Jan]电话网络
- 【bzoj1596】[Usaco2008 Jan]电话网络 树形dp
- bzoj1596 [Usaco2008 Jan]电话网络
- 【bzoj1596】[Usaco2008 Jan]电话网络
- [bzoj 1596][Usaco2008 Jan]电话网络
- 【BZOJ】1596: [Usaco2008 Jan]电话网络
- BZOJ1596: [Usaco2008 Jan]电话网络
- Bzoj 1596: [Usaco2008 Jan]电话网络