问题来源:刘汝佳《算法竞赛入门经典--训练指南》 P70 例题30:

问题描述:有给你一个n个点m条边(m<n<=1000)的无向无环图,在尽量少的节点上放灯,使得所有边都被照亮,每盏灯将照亮以它为一个端点的所有边。在灯的总数最小的前提下,被两盏灯同时照亮的边数尽量大。

问题分析:1.题中的图,是由多颗树构成的森林,对每颗树用相同的方法即可。

       2.本题优化目标:放置的街灯数a应尽量少,在a尽量少的情况下,被两盏灯同时照亮的边数b尽量大(即只被一盏灯照亮的边数c尽量小(b+c=m)),两个要求可合并为一个要求,即x(x=Ma+c),(要求无论c怎么取值都不会影响a的取值,M是一个比c的最大理论值还要大的数即可)

       3.对于树上的每一个节点i,只有两种状态,放灯和不放灯,i的状态将影响其子节点的决策,则可以将父节点(fa)的状态加入状态表示中,设i点的状态为dp[i][j],其中若j=0表示节点i的父亲节点(fa)没有放灯,若j=1表示fa放灯了:

        决策1:节点i不放灯,必须保证j==1(fa放灯) || i为根节点,此时dp[i][j] = Sum{dp[k][0] | k为取遍i的所有子节点}

             如果i不是根dp[i][j]++(i与fa之间只有一盏灯);

        决策2:节点i放灯,此时dp[i][j] = Sum{dp[k][1] | k为取遍i的所有子节点}+M

             如果j==0 && i不为根节点dp[i][j]++(i与fa之间只有一盏灯);

例题链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1800

例题:UVa 10891

10859 - Placing Lampposts

Time limit: 3.000 seconds

  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.

Input

  There will be several cases in the input file. The first line of input will contain an integer T(T<=30) that will determine the number of test cases. Each case will start with two integers N(N<=1000) and M( M<N) that will indicate the number of junctions and roads respectively. The junctions are numbered from 0 to N-1. Each of the next M lines will contain two integers a and b, which implies there is a road from junction a to b,
( 0<= a,b < N ) and a != b. There is a blank line separating two consecutive input sets.

Output

  For each line of input, there will be one line of output. Each output line will contain 3 integers, with one space separating two consecutive numbers. The first of these integers will indicate the minimum number of lampposts required to light the whole city. The second integer will be the number of roads that are receiving lights from two lampposts and the third integer will be the number of roads that are receiving light from only one lamppost.

Sample Input

2
4 3
0 1
1 2
2 3

5 4
0 1
0 2
0 3
0 4

Sample Output

2 1 2
1 0 4

代码实现:

 1 #include "cstdio"
 2 #include "cstring"
 3 #include "vector"
 4 using namespace std;
 5
 6 #define N 1005
 7 #define M 2000
 8 int n,m;
 9 int dp[N][2]; //对于每个节点,只有两种状态(1:选,0:不选)
10 int vis[N][2];  //标记
11 vector<int> adj[N];
12
13 int inline Min(int a,int b)
14 {
15     return a<b?a:b;
16 }
17
18 void Init()
19 {
20     for(int i=0; i<n; i++)
21         adj[i].clear();
22     memset(vis,0,sizeof(vis));
23 }
24
25 int DFS(int i,int j,int fa)
26 {
27     if(vis[i][j]) return dp[i][j];
28     vis[i][j] = 1;
29     int& ans = dp[i][j];
30     ans = 2000; //先考虑放灯的情况
31     for(int k=0; k<adj[i].size(); k++)
32     {
33         if(adj[i][k]==fa) continue;
34         ans += DFS(adj[i][k],1,i); //在i放灯的情况下,i的子节点放灯的情况
35     }
36     if(j==0 && fa>=0) ans++; //父节点没有放灯(j==0) 并且i不为根节点(fa!=-1),则点i和点fa相连的这条边只有一盏灯照亮,ans++;
37     if(j==1 || fa<0) //i为根节点(fa==-1),或者父亲节点放灯了(j==1),就可以考虑i点不放灯.
38     {
39         int sum = 0;
40         for(int k=0; k<adj[i].size(); k++)
41             if(adj[i][k]!=fa)
42                 sum += DFS(adj[i][k],0,i);
43         if(fa>=0) sum++; //如果i不是根,则点i和点fa相连的这条边只有一盏灯照亮,sum++;
44         ans = Min(ans,sum);
45     }
46     return ans;
47 }
48
49 int main()
50 {
51     int T;
52     int i;
53     int x,y;
54     int ans;
55     scanf("%d",&T);
56     while(T--)
57     {
58         scanf("%d %d",&n,&m);
59         Init();
60         ans = 0;
61         for(i=1; i<=m; i++)
62         {
63             scanf("%d %d",&x,&y);
64             adj[x].push_back(y);
65             adj[y].push_back(x);
66         }
67         for(i=0; i<n; i++)
68         {
69             if(vis[i][0]==1) continue;
70             ans += DFS(i,0,-1);  //i为树根,没有父节点(-1),父节点设为不放灯(0);
71         }
72         printf("%d %d %d\n",ans/2000,m-ans%2000,ans%2000);
73     }
74     return 0;
75 }

转载于:https://www.cnblogs.com/ruo-yu/p/4391774.html

10_放置街灯(Placing Lampposts,UVa 10859)相关推荐

  1. UVA10859 放置街灯 Placing Lampposts(树状DP)

    UVA10859 放置街灯 Placing Lampposts(树状DP) 这道题有两种解决方法,因为原图保证无重边无环无自环, 所以原图一定是一颗树(或森林).,都是树状DP,但是实现的过程大同小异 ...

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

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

  3. Placing Lampposts ,UVa 10859 树形dp

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

  4. Placing Lampposts UVA - 10859 放置街灯 树形dp

    As a part of the mission 'Beautification of Dhaka City', the government has decided to replace all t ...

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

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

  6. [动态规划] 放置街灯 Uva 10859 - Placing Lampposts

    [动态规划] 放置街灯 Uva 10859 - Placing Lampposts 英文题目: As a part of the mission �Beautification of Dhaka Ci ...

  7. UVA - 10859 Placing Lampposts 放置街灯

    Placing Lampposts 传送门:https://vjudge.net/problem/UVA-10859 题目大意:给你一片森林,要求你在一些节点上放上灯,一个点放灯能照亮与之相连的所有的 ...

  8. uva 10859 放置街灯树形dp

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

  9. 树形DP(放置街灯,uva 10859)

    前面也做了一道很像的题,那道题只要求放置的数目最少,要求覆盖的是点.在这题中,要求覆盖的是边,不但要求放着的数目最少,更要求覆盖两次的边最多.因此贪心法不再适用,最少要多少个点可以贪心求出,但是同时要 ...

最新文章

  1. 2018年爱奇艺校招笔试
  2. vs中将网站aspx.cs文件打包成一个dll
  3. 使用文本用户界面(NMTUI)进行网络配置
  4. 编程python用什么软件比较好-新手入门Python编程的8个实用建议
  5. Java经典逻辑编程题(不死神兔问题)
  6. 【数据结构与算法】之深入解析“环形链表II”的求解思路与算法示例
  7. C - Maximize GCD(简单数论)
  8. Linux 内核通知链和例程代码
  9. 解释http和html,解释HTTP、HTML的含义
  10. 101-字符串类string基础使用
  11. python用方括号提取字符中的数值_Python使用re模块正则提取字符串中括号内的内容示例...
  12. 如何防止通过url攻击_百和情缘答疑:通过网上征婚相亲如何防止被骗?
  13. html英文参考文献,英文参考文献标准格式
  14. ZOJ3551 Bloodsucker(概率dp)
  15. Emscripten 单词_真正的英语大神绝不死背单词! 他们用这种方法一周突破3500词
  16. ZigBee Dotdot
  17. Unity PSD导入到Unity
  18. 解决 C# GetPixel 和 SetPixel 效率问题
  19. 麒麟系统查看微信聊天记录位置、微信收到的文件位置
  20. this指向,并改变this指向

热门文章

  1. PIL.image保存图片
  2. 移动App统计指标汇总
  3. 【论文分享】ACL 2020 神经网络的可解释性
  4. elasticsearch rpm安装及详细配置
  5. [机缘参悟-14]:哲学、唯物主义、唯心主义与空无主义
  6. DOS下Debug工具使用
  7. 图扑软件与华为云共同构建新型智慧工厂
  8. Android studio 利用MPAndroidChart制作饼图
  9. 通过计算机名查找当前域用户名,局域网中怎样通过IP查找计算机名
  10. Python中通过property实现属性的修改、删除、查看