【UVA12093】Protecting Zonk (树形DP)
题意:
给定一个有n个节点的无根树,有两种装置A和B,每种都有无限多个。在某个节点X使用A装置需要C1的花费,并且此时与节点X相连的边都被覆盖。在某个节点X使用B装置需要C2的花费,并且此时与节点X相连的边以及与X相连的点相连的边都被覆盖。求覆盖所有边的最小花费。
分析:
首先无根树可以先dfs确定根。考虑选择装置A和装置B的影响。
装置A只会影响节点u连出去的边。而装置B还会影响u相连的点相连的边,也就是说与节点u距离为2的边也会被影响。
也就是说,对于边(u,fa[u]),如果fa[fa[u]]装上装置B,那么这条边就被覆盖。但只有这种情况吗?有一个容易漏的情况就是如果u、v的父亲都是fa[u],如果在v上装了装置B,那么边(u,fa[u])就被覆盖了。(像我这种想东西不全面的人就容易把这种情况漏掉,导致我后来整个代码重打了一遍~~)
而对于装置A,处理过程就相对简单了,下面我只说说我怎么处理装置B的。
用了个四维DP,dp[x][a][b][c](a=0~2; b=0~2; c=0~1)表示节点x,选了a装置(0表示不选,1表示装置A,2表示装置B),fa[x]选了b装置,目前边(u,fa[u])的状态为c。
如果c=0,那么u的子节点中一定要有至少一个装上装置B。而对于上述说的装置B的第二种情况,我们也可以用这个一起计算。
那么就是两种方案:
1、u的子节点中至少有一个装上装置B。
2、u的子节点中没有装上装置B的。
当符合条件时,取两者的min值即可。
代码如下:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Maxn 10010
#define INF 100000010 int dp[Maxn][][][];
int first[Maxn],fa[Maxn];
int n,c1,c2; struct node
{
int x,y,next;
}t[*Maxn];int len; void ins(int x,int y)
{
t[++len].x=x;t[len].y=y;
t[len].next=first[x];first[x]=len;
} int mymin(int x,int y) {return x<y?x:y;} void dfs(int x,int f)
{
fa[x]=f;
for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
{
int y=t[i].y;
dfs(y,x);
}
} int ffind(int x,int a,int b,int c)// a->x b->fa c->(x,fa[x])
{
if(dp[x][a][b][c]<INF) return dp[x][a][b][c];
int ans=dp[x][a][b][c];
int p=(a!=||b==)?:,h=,y,now;
for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x])//sons have at least one B
{
y=t[i].y;
now=mymin(mymin(ffind(y,,a,),ffind(y,,a,)),ffind(y,,a,));
h+=now;
}
for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x])
{
y=t[i].y;
now=mymin(mymin(ffind(y,,a,),ffind(y,,a,)),ffind(y,,a,));
ans=mymin(ans,h-now+ffind(y,,a,));
}
if(c!=) //sons have no B
{
now=;
for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x])
{
y=t[i].y;
now+=mymin(ffind(y,,a,p),ffind(y,,a,));
}
ans=mymin(ans,now);
}
if(a==) ans+=c1;
else if(a==) ans+=c2;
dp[x][a][b][c]=ans;
return ans;
} int main()
{
while()
{
scanf("%d%d%d",&n,&c1,&c2);
if(n==&&c1==&&c2==) break;
len=;
memset(first,,sizeof(first));
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ins(x,y);ins(y,x);
}
memset(dp,,sizeof(dp));
dfs(,);
int ans=INF;
ans=mymin(ans,ffind(,,,));
ans=mymin(ans,ffind(,,,));
ans=mymin(ans,ffind(,,,));
printf("%d\n",ans);
}
return ;
}
UVA12093
2016-03-10 17:16:10
【UVA12093】Protecting Zonk (树形DP)的更多相关文章
- UVa 12093 Protecting Zonk (树形DP)
题意:给定一个有n个节点的无根树,有两种装置A和B,每种都有无限多个.在某个节点X使用A装置需要C1的花费,并且此时与节点X相连的边都被覆盖.在某个节点X使用B装置需要C2的花费,并且此时与节点X相连 ...
- poj3417 LCA + 树形dp
Network Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4478 Accepted: 1292 Descripti ...
- COGS 2532. [HZOI 2016]树之美 树形dp
可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...
- 【BZOJ-4726】Sabota? 树形DP
4726: [POI2017]Sabota? Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 128 Solved ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- 树形DP
切题ing!!!!! HDU 2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...
- BZOJ 2286 消耗战 (虚树+树形DP)
给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...
- POJ2342 树形dp
原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...
- hdu1561 The more, The Better (树形dp+背包)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...
- bzoj2500: 幸福的道路(树形dp+单调队列)
好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...
随机推荐
- kafka Windows客户端Linux服务器---转
原文:http://blog.csdn.net/jingshuigg/article/details/25001979 一.对于服务器端的搭建可以参考上一篇文章:kafka单机版环境搭建与测试 服务器 ...
- Android BLE开发——Android手机与BLE终端通信初识
蓝牙BLE官方Demo下载地址: http://download.csdn.net/detail/lqw770737185/8116019参考博客地址: http://www.eoeandr ...
- android开发之Parcelable使用详解
想要在两个activity之间传递对象,那么这个对象必须序列化,android中序列化一个对象有两种方式,一种是实现Serializable接口,这个非常简单,只需要声明一下就可以了,不痛不痒.但是a ...
- 如何让Windows程序只运行一个程序实例?
要实现VC++或者MFC只运行一个程序实例,一般采用互斥量来实现,即首先用互斥量封装一个只运行一个程序实例的函数接口: HANDLE hMutex = NULL; void MainDlg::RunS ...
- Java线性表的排序
Java线性表的排序 ——@梁WP 前言:刚才在弄JDBC的时候,忽然觉得order-by用太多了没新鲜感,我的第六感告诉我java有对线性表排序的封装,然后在eclipse里随便按了一下“.” ,哈 ...
- 20、CSS
CSS 层叠样式表(Cascading Style Sheets). 用于定义显示HTML样式. DIV和SPAN div是块级元素. span是行级元素. 将一些页面中的内容包裹起来统一设置样式. ...
- .Net程序员学习Linux(一)
本次知识点:Linux系统的多终端切换,linux下的用户,linux远程访问工具使用,linux下重要的目录,命令的组成,通配符,linux的路径问题,文件操作的综合运用 为什么学习linux? 1 ...
- Android开发手记(18) 数据存储三 SQLite存储数据
Android为数据存储提供了五种方式: 1.SharedPreferences 2.文件存储 3.SQLite数据库 4.ContentProvider 5.网络存储 SQLite 是以嵌入式为目的 ...
- android中sharedPreferences的笔记
haredPreferences的使用非常简单,能够轻松的存放数据和读取数据.SharedPreferences只能保存简单类型的数据,例如,String.int等.一般会将复杂类型的数据转换成Bas ...
- MSSQL 各个发行版本版本号以及Compact 版本号
终于开始写博客了. 不要笑啊. 下面是MSSQL 的发行版本以及版本号.自己整理的. http://support.microsoft.com/kb/321185/zh-cn SQL Server 2 ...