As a part of the mission ‘Beautification of Dhaka City’, the government has decided to replace all the old lampposts with new expensive ones. Since the new ones are quite expensive and the budget is not up to the requirement, the government has decided to buy the minimum number of lampposts required to light the whole city.

Dhaka city can be modeled as an undirected graph with no cycles, multi-edges or loops. There are several roads and junctions. A lamppost can only be placed on junctions. These lampposts can emit light in all the directions, and that means a lamppost that is placed in a junction will light all the roads leading away from it.

The ‘Dhaka City Corporation’ has given you the road map of Dhaka city. You are hired to find the minimum number of lampposts that will be required to light the whole city. These lampposts can then be placed on the required junctions to provide the service. There could be many combinations of placing these lampposts that will cover all the roads. In that case, you have to place them in such a way that the number of roads receiving light from two lampposts is maximized.

分析:设a表示放置灯数(尽量小),一盏灯照亮的边数为c(尽量小),用x = Ma+b表示最小化目标,其中M是一个很大的正整数(M比a的最大理论值和c的最小理论值之差还要大),则 a = x/M, b = x%M,主要连个优化条件就变成了一个。

设d(i,j)表示以i为根节点的子树的最小值x。j表示i的父节点是否放灯(1放,0没放)。

【分析】
无向无环图的另一个说法是“森林”, 它由多棵树组成。 动态规划是解决树上的优化问题的常用工具, 本题就是一个很好的例子。首先, 本题的优化目标有两个: 放置的灯数a应尽量少, 被两盏灯同时照亮的边数b应尽量大。 为了统一起见, 我们把后者替换为: 恰好被一盏灯照亮的边数c应尽量小, 然后改用x=Ma+c作为最小化的目标, 其中M是一个很大的正整数。 当x取到最小值时,x/M的整数部分就是放置的灯数的最小值; x%M就是恰好被一盏灯照亮的边数的最小值。
一般来说, 如果有两个需要优化的量v1和v2, 要求首先满足v1最小,在v1相同的情况下v2最小, 则可以把二者组合成一个量Mv1+v2, 其中M是一个比“v2的最大理论值和v2的最小理论值之差”还要大的数。 这样, 只要
两个解的v1不同, 则不管v2相差多少, 都是v1起到决定性作用; 只有当v1相同时, 才取决于v2。

在本题中, 可以取M=2000。每棵树的街灯互不相干, 因此可以单独优化, 最后再把答案加起来即可。 下面我们只考虑一棵树的情况。 首先对这棵树进行DFS, 把无根树转化为有根树, 然后试着设状态d(i) 为以i为根的子树的最小x值, 看看能不能写出状态转移方程。
决策只有两种: 在i处放灯和不在i处放灯。 后继状态是i的各个子结点。 可是问题来了: i处是否放灯将影响到其子结点的决策。 因此, 我们需要把“父结点处有没有放灯”加入状态表示中。 新状态为:d(i,j) 表示i的父结点“是否放灯”的值为j(1表示放灯,0表示没放) , 以i为根的树的最小x值(算上i和其父结点这条边) 。
注意到各子树可以独立决策, 因此可作出如下决策。
决策一: 结点i不放灯。 必须j=1或者i是根结点时才允许作这个决123策。 此时d(i,j) 等于sum{d(k,0) |k取遍i的所有子结点} 。 如果i不是根, 还得加上1, 因为结点i和其父结点这条边上只有一盏灯照亮。
决策二: 结点i放灯。 此时d(i,j) 等于sum{d(k,1) |k取遍i的所有子结点} +M。 如果j=0且i不是根, 还得加上1, 因为结点i和其父结点这条边只有一盏灯照亮。用数学式子很难表达上面的状态转移, 但用程序表达却可以很清晰

#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int N = 1000+5, M = 2000;
vector<int> g[N];  // 森林是稀疏的,这样保存省空间,枚举相邻结点也更快
int d[N][2], vis[N][2];
// 在DFS的同时进行动态规划,f是i的父结点,它不存入状态里
int dp(int i,int j, int f){if(vis[i][j]) return d[i][j];vis[i][j] = 1;int &ans = d[i][j];// 森林是稀疏的,这样保存省空间,枚举相邻结点也更快ans = M;  灯的数量加1,x加Mfor(int k = 0; k < g[i].size(); k++)if(g[i][k] != f)ans += dp(g[i][k], 1, i); if(!j && f >= 0) ans++; // 如果i不是根,且父结点没放灯(即父节点只有一盏灯),则x加1    // i是根或者其父结点已放灯,i才可以不放灯if(f < 0 || j == 1){ int sum = 0;for(int k = 0; k < g[i].size(); k++)if(g[i][k] != f)sum += dp(g[i][k], 0, i);if(f >= 0) sum++; // 如果i不是根(即i只有一盏灯),则x加1ans = min(ans, sum);} return ans;
}
int main(int argc, char** argv) {int T;scanf("%d",&T);while(T--){int n, m;scanf("%d%d",&n,&m);for(int i = 0; i < n; i++) // g里保存着上一组数据的值,必须清空 g[i].clear(); for(int i = 0; i < m; i++){int u, v;scanf("%d%d",&u,&v);g[u].push_back(v);g[v].push_back(u);}int ans = 0;memset(vis, 0, sizeof(vis));for(int i = 0; i < n; i++) if(!vis[i][0]) // 新的一棵树ans += dp(i, 0, -1); // i是树根,因此父结点不存在(-1) printf("%d %d %d\n", ans/M, m-ans%M, ans%M); //从x计算3个整数} return 0;
}

Placing Lampposts UVA - 10859 放置街灯 树形dp相关推荐

  1. uva 10859 放置街灯树形dp

    首先,本题的优化目标有两个:放置的街灯a应该尽量少:被两灯同时照亮的边数b应该尽量大.为了统一起见,我们把后者替换为:恰好被一盏灯照亮的边数c应该尽量小,然后改用x = Ma+c作为优化目标,其中一个 ...

  2. 10_放置街灯(Placing Lampposts,UVa 10859)

    问题来源:刘汝佳<算法竞赛入门经典--训练指南> P70 例题30: 问题描述:有给你一个n个点m条边(m<n<=1000)的无向无环图,在尽量少的节点上放灯,使得所有边都被照 ...

  3. uva 10859 放置街灯--Placing Lampposts

    uva 10859 - Placing Lampposts(树形dp ###两个别人家的代码,没有注释看了很久 ###所以自己改写了一遍,附注释 https://blog.csdn.net/keshu ...

  4. Placing Lampposts ,UVa 10859 树形dp

    UVa 10859 日常刷白书,第三次刷dp刷到这题,竟然还是不会写..... 这个题给定n个点m条边的无向无环图,有至多1000个节点,每个节点有两个状态,可以放灯或者不放灯,要求放最少的灯使得所有 ...

  5. UVA 10859 放置街灯(树形DP)

    把无向图转化成有根树. 两个优化的量v1,v2,把二者组合成一个量Mv1+v2,让M是一个比"v2的最大理论值和v2的最小理论值之差"还要大的数, 就可以先决定v1,再决定v2. ...

  6. uva 1218 Perfect Service 树形dp

    // uva 1218 Perfect Service 树形dp // // 解题思路: // // d[u][0]表示节点本身是服务器 // d[u][1]表示节点的父节点是服务器 // d[u][ ...

  7. UVA - 1218 Perfect Service(树形dp)

    题目链接:UVA - 1218 Perfect Service 题意 有n台电脑,互相以无根树的方式连接,现要将其中一部分电脑作为服务器,且要求每台电脑必须连接且只能连接一台服务器(不包括作为服务器的 ...

  8. BZOJ 2314 士兵的放置(play) 树形DP

    题目大意:给定一棵树,求最小支配集以及最小支配集数量 首先我们需要会求最小支配集- - 其实支配集的求法很优雅的= = 那些第一问就写了一大坨的第二问还怎么写- - 可以自己YY一下简单的支配集求法= ...

  9. uva10859放置街灯(树形dp)

    例题 30 放置街灯( Placing Lampposts, UVa 10859 ) 给你一个 n 个点 m 条边的无向无环图, 在尽量少的结点上放灯, 使得 所有边都被照亮. 每盏灯将照亮以它为一个 ...

最新文章

  1. 关于String数组的用法
  2. 我妈今年 70 岁,受不了Windows蓝屏,用了 21 年的 Linux!YYDS!
  3. 18香警告:一个女生勿近的邪恶开源项目...
  4. anaconda 怎么安装xlrd_Anaconda 安装 tensorflow 和 keras
  5. 云计算的关键特点及挑战
  6. TBXML常用API
  7. 《个体软件过程》—第1章1.3节个体软件过程
  8. 网易“吃鸡”,干腾讯何事?
  9. 《Thinking in Java》Ten 内部类
  10. SQL Server 2008 R2 彻底卸载
  11. 友华PT925E,电信天翼网关3.0,光猫超级密码获取最简便方式
  12. iTerm2配置(rz/sz命令)
  13. tensorflow学习之二 alexnet vgg resnet目标分类
  14. linux获取ip上网,linux dhcp 获取ip地址能上网,设置静态ip地址则不能上网
  15. Button 英文大写问题
  16. 神舟战神笔记本怎么U盘装Win10系统教学
  17. win10系统cf连接服务器失败,cf与服务器连接失败
  18. 软件测试专业英文词汇,软件测试专业词汇中英文对照
  19. 如何识别图片表格?在线扫描识别表格的方法分享
  20. Xinlinx zynq7020国产替代 FMQL20S400 全国产化 ARM 核心板+扩展板

热门文章

  1. pulseaudio-webrtc-audio-processing的编译环境搭建
  2. 被繁杂的数据搞到头大?让 Google Cloud 大数据平台帮你实现快准狠!
  3. Tomcat8.0系列配置GlobalSign SSL证书
  4. 简要的可行性分析报告(1)
  5. 我的达内Java培训经历
  6. 基于Android的微信主界面
  7. 零基础创建自定义gym环境——以股票市场为例
  8. 教教你如何配置汤姆猫 和 Java 环境变量的设置
  9. 连接可用AP,提示“已连接,但无法访问互联网”,过一会变成“网络连接受限”,实际可以上网
  10. C/C#实现RSA签名