Placing Lampposts - UVa 10859 树形dp

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

题意:有n个点和m条街,每个点上可以装一个路灯,每条街都必须在两端至少有一个灯,问至少需要多少个灯,如果灯数相同的情况下,最多有多少条街可以在两端都有路灯。

思路:简单的树形dp,就是本题可能不止是一棵树。dp[u][0 1][k]表示在u节点不安装/安装路灯的情况,dp[u][k][0 1]表示u节点及其以下的街都满足要求是最少的路灯数和最大的两端都有灯的街数。

AC代码如下:

[cpp] view plaincopy

    1. #include<cstdio>
    2. #include<cstring>
    3. #include<vector>
    4. using namespace std;
    5. int n,m,dp[1010][2][2],vis[1010];
    6. vector<int> vc[1010];
    7. void dfs(int u,int f)
    8. {
    9. vis[u]=1;
    10. dp[u][1][0]=1;
    11. int i,j,k,len=vc[u].size(),v;
    12. for(i=0;i<len;i++)
    13. {
    14. v=vc[u][i];
    15. if(v==f)
    16. continue;
    17. dfs(v,u);
    18. dp[u][0][0]+=dp[v][1][0];
    19. dp[u][0][1]+=dp[v][1][1];
    20. if(dp[v][0][0]<dp[v][1][0])
    21. {
    22. dp[u][1][0]+=dp[v][0][0];
    23. dp[u][1][1]+=dp[v][0][1];
    24. }
    25. else if(dp[v][0][0]>dp[v][1][0])
    26. {
    27. dp[u][1][0]+=dp[v][1][0];
    28. dp[u][1][1]+=dp[v][1][1]+1;
    29. }
    30. else
    31. {
    32. dp[u][1][0]+=dp[v][0][0];
    33. dp[u][1][1]+=max(dp[v][0][1],dp[v][1][1]+1);
    34. }
    35. }
    36. }
    37. int main()
    38. {
    39. int T,t,i,j,k,u,v,a,b,c;
    40. scanf("%d",&T);
    41. for(t=1;t<=T;t++)
    42. {
    43. scanf("%d%d",&n,&m);
    44. for(i=0;i<n;i++)
    45. vc[i].clear();
    46. for(i=1;i<=m;i++)
    47. {
    48. scanf("%d%d",&u,&v);
    49. vc[u].push_back(v);
    50. vc[v].push_back(u);
    51. }
    52. memset(dp,0,sizeof(dp));
    53. memset(vis,0,sizeof(vis));
    54. a=0;b=0;c=0;
    55. for(i=0;i<n;i++)
    56. if(vis[i]==0)
    57. {
    58. dfs(i,-1);
    59. if(dp[i][0][0]<dp[i][1][0])
    60. a+=dp[i][0][0],b+=dp[i][0][1];
    61. else if(dp[i][0][0]>dp[i][1][0])
    62. a+=dp[i][1][0],b+=dp[i][1][1];
    63. else
    64. a+=dp[i][0][0],b+=max(dp[i][0][1],dp[i][1][1]);
    65. }
    66. printf("%d %d %d\n",a,b,m-b);
    67. }
    68. }
时间: 2024-11-09 01:09:40

Placing Lampposts - UVa 10859 树形dp的相关文章

UVA 10859 树形DP

很明显的树形DP了,设状态dp[i][0],dp[i][1].枚举子节点放或不放的两种状态. 在此学到一种不同于一般处理的方法,题目要求被两灯照亮的边尽量多,反过来即被一灯照亮的尽量少设为e.又需要的灯尽量少设为v. 设M是一个很大的数,则M*v+e即是所求.由于M很大,所以主导作用取决于v,只要v不同M*v+e一定不会相同.当v相同,被一灯照亮的尽量少即v此时发挥作用.所以DP时只需要保存这种状态即可. #include <iostream> #include <cstdio>

uva 1292(树形dp)

题意:有一个树,上面有n个结点,给出每个结点有边相连的直接相邻的点,问最少选几个点能让所有的边至少有一个结点被选中. 题解:树形dp简单题,把0当做根节点. f[i][0]:不选i点,覆盖所有边的最少点 f[i][1]:选i点,覆盖所有边的最少点 状态转移方程: f[u][1] += min(f[v][1], f[v][0]);//v是u的子节点,选u点子节点可以选或不选 f[u][0] += f[v][1];//不选u点就一定要选子节点,这样保证边能覆盖 #include <stdio.h>

uva 12223(树形dp)

题意:一个城市有n个景点,景点和景点之间的路线形成一棵无根树(也就是有n-1条边),给出景点之间的花费,一个人可以任选一个景点住在那里,然后他每年都要固定去m个景点,给出这m个景点和要去的次数,这个人每次去了景点都会回家,问他一年为了观赏景点最少花费多少钱. 题解:想了好久,看看题解才完全理解.要先把无根树转化成有根树,默认让1成为根节点,然后先dfs把每个节点v当做根节点的子树的节点数统计一下在num[v]中,因为计算u-v边的走到次数就是以v为根节点的子树的节点数的个数乘边的权值乘2(来回)

uva 10859 Placing Lampposts,树形dp

// uva 10859 Placing Lampposts // 树形dp // // 题目的意思是一个无向无环图中,有一些顶点和一些边 // 要在顶点上放置灯笼(灯笼可以照亮与它相邻接的点), // 使得所有的边都能被灯笼照亮,其中可能有一些边被两个灯笼 // 照亮,则要求使得所有边都被灯笼照亮所需灯笼的最小值, // 并且,此时边同时被两个灯笼照亮的数目应尽可能的多 // // 思路是 // d[i][0]表示在节点i不放置灯笼所需的灯笼的最小值 // d[i][1]表示在节点i放置灯笼所

UVA 10859 - Placing Lampposts 树形DP、取双优值

                          Placing Lampposts As a part of the mission ‘Beauti?cation of Dhaka City’, the government has decided to replace all theold lampposts with new expensive ones. Since the new ones are quite expensive and the budget is notup to

UVA 10859 Placing Lampposts(树DP)

题意:给一个n个顶点m条边的无向无环图,在尽量少的结点上放灯,使得所有边都被照亮.每盏灯将照亮以它为一个端点的所有边.在灯的总数最小的前提下,被两盏灯同时照亮的变数应该尽量大. 思路:无向无环图就是"森林",常用树形dp,本题要优化的目标有两个,放置的灯数a应尽量少,被两盏灯同时照亮的边数b应尽量大,为了统一,我们把b替换成"恰好被一盏灯照亮的边数c尽量小".然后设x=Ma+c为最终的优化目标,M是一个很大的正整数.当x取最小值的时候,x/M就是a的最小值,x%M就

UVA - 1218 Perfect Service(树形dp)

题目链接:id=36043">UVA - 1218 Perfect Service 题意 有n台电脑.互相以无根树的方式连接,现要将当中一部分电脑作为server,且要求每台电脑必须连接且仅仅能连接一台server(不包含作为server的电脑).求最少须要多少台电脑作为server. 思路 典型的树形dp问题,那么我们来建立模型. d(u,0):u是server,孩子是不是server均可 d(u,1):u不是server,u的父亲是server,u的孩子不能是server d(u,2)

uva 12186 Another Crisis 树形dp

// uva 12186 Another Crisis 树形dp // // 对于一个节点u,有k个子节点,则至少有c = (k * T - 1) / 100 + 1才能 // 发信,即c / k >= T / 100,则 c 的值为 k * T /100,上取整变成上式 // 将所有的子节点d从小到大排序,取前c个就是d[u]的值 // 紫书上的一题,之前看了好久好久,觉得挺好的,然而一直没做,今天就来 // 体验体验,挺好的一题,注意一下,如果一个节点是叶节点,直接return 1就好 //

uva 1220 - Party at Hali-Bula 【入门树形dp】

题目:uva 1220 - Party at Hali-Bula 题意:一个公司员工要举行聚会,要求任意一个人不能和他的直接上司同时到场,一个员工只有一个支系上司,现在求最多有多少人到场,并且方案是否唯一 分析:分析发现是要求一个树的最大独立集.这里可以用树形dp解决. 定义dp[x][0]:表示在 i 点不选 i 点的以 x 为子树的最大独立集 而dp[x][1] 表示x到场的最大独立集 定义f [x][0]:表示以x为根且x点不选的子树是否唯一 ,f[x][1]表示以x为根且x选的子树是否唯