POJ 3659 Cell Phone Network(树形DP)
2016-03-13 22:43
477 查看
Description
给出一棵点数为n的树,求这棵树的最小点覆盖
Input
第一行为一整数n表示树的点数,之后n-1行每行两个整数a和b表示树上a和b之间有一条边
Output
输出这棵树的最小点覆盖
Sample Input
5
1 3
5 2
4 3
3 5
Sample Output
2
Solution
dp[i][0]表示i属于支配集,并且以i为根的子树都被覆盖的情况下支配集的最少点数
dp[i][1]表示i不属于支配集,且以i为根的子树都被覆盖,且i被其中不少于一个子节点覆盖的情况下支配集的最少点数
dp[i][2]表示i不属于支配集,且以i为根的子树都被覆盖,且i没被子节点覆盖的情况下支配集的最少点数
dp[i][0]=1+sum(min(dp[u][0],dp[u][1],dp[u][2]))
dp[i][1]=INF i没有子节点
dp[i][1]=sum(min(dp[u][0],dp[u][1]))+inc i有子节点
inc=0若sum(min(dp[u][0],dp[u][1]))包含某个dp[u][0]
否则inc=min(dp[u][0]-dp[u][1])
dp[i][2]=sum(dp[u][1])
Code
给出一棵点数为n的树,求这棵树的最小点覆盖
Input
第一行为一整数n表示树的点数,之后n-1行每行两个整数a和b表示树上a和b之间有一条边
Output
输出这棵树的最小点覆盖
Sample Input
5
1 3
5 2
4 3
3 5
Sample Output
2
Solution
dp[i][0]表示i属于支配集,并且以i为根的子树都被覆盖的情况下支配集的最少点数
dp[i][1]表示i不属于支配集,且以i为根的子树都被覆盖,且i被其中不少于一个子节点覆盖的情况下支配集的最少点数
dp[i][2]表示i不属于支配集,且以i为根的子树都被覆盖,且i没被子节点覆盖的情况下支配集的最少点数
dp[i][0]=1+sum(min(dp[u][0],dp[u][1],dp[u][2]))
dp[i][1]=INF i没有子节点
dp[i][1]=sum(min(dp[u][0],dp[u][1]))+inc i有子节点
inc=0若sum(min(dp[u][0],dp[u][1]))包含某个dp[u][0]
否则inc=min(dp[u][0]-dp[u][1])
dp[i][2]=sum(dp[u][1])
Code
#include<cstdio> #include<iostream> #include<cstring> using namespace std; #define maxn 11111 #define INF 0x3f3f3f3f typedef long long ll; struct Edge { int to,next; }edge[2*maxn]; int n,head[maxn],tot; int dp[maxn][3]; void init() { tot=0; memset(head,-1,sizeof(head)); for(int i=0;i<maxn;i++)dp[i][1]=INF; } void add(int u,int v) { edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } void DP(int u,int fa) { dp[u][0]=1,dp[u][2]=0; int sum=0,inc=INF,flag=0; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].to; if(v==fa)continue; DP(v,u); dp[u][0]+=min(dp[v][0],min(dp[v][1],dp[v][2])); if(dp[v][0]<=dp[v][1]) sum+=dp[v][0],flag=1; else sum+=dp[v][1],inc=min(inc,dp[v][0]-dp[v][1]); if(dp[v][1]!=INF&&dp[u][2]!=INF)dp[u][2]+=dp[v][1]; else dp[u][2]=INF; } if(inc!=INF&&!flag)dp[u][1]=INF; else { dp[u][1]=sum; if(!flag)dp[u][1]+=inc; } } int main() { while(~scanf("%d",&n)) { init(); for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); add(u,v),add(v,u); } DP(1,1); int ans=min(dp[1][0],dp[1][1]); printf("%d\n",ans); } return 0; }
相关文章推荐
- Lock与synchronized 的区别
- 即将毕业的程序员历程总结
- 找到Qt程序所有依赖库的简便方法,带翻译文件
- 菜鸟不要怕,看一眼,你就会用GCD,带你装逼带你飞
- plsql语句块 for 遍历游标
- Codeforces650B Image Preview
- 整体流程
- js scrollTop, 滚动条操作
- 16.3.13(晴)
- 测试MarkDown
- 新手学习Linux之grep
- Unity3D 5 官方教程:标准着色器之材质参数(二)
- elk示例-精简版2
- struts2开发javaWeb 项目时遇到jar包冲突问题的解决办法
- 【hdu2199】Can you solve this equation?——二分
- setWindowFlags(Qt::FramelessWindowHint);使得窗体透明的问题解决
- BestCoder Round #75 1002模拟
- 算法基础:递归---汉诺塔问题
- 第一次C++作业-2
- 小学生二元四则运算(F)