首页 > 代码库 > UVA 10859 Placing Lampposts
UVA 10859 Placing Lampposts
Description
InputAs 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.
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 |
Problem Setter: Sohel Hafiz.
Special thanks to Per Austrin.
好久没做过树DP了,这树白书上面一条基础的树DP ..
在这题目上面也学到很很多技巧。
题目意思是可以在某一点上放一个灯,这个灯可以照亮它所有的边。
要求计算出森林上面每一条边都要被灯光覆盖的前提下。
被两盏灯照亮的边尽量多。因为一条路最多只能够被两盏灯照亮。
然后转换题意就是在所有边都被灯光照亮的前提下。被一盏灯照亮的边尽量少。
我们可以设 x = M * v1 + v2 .... M是一个大于v2的理论最大值的系数。
那么无论v2取最再大。。也无法影响到v1的优先级。
然后,设一个状态 dp[i][j]( 0 <=i < 1000 , j == 0 || j == 1 ) ..
表示第i个点..其父亲有没放灯(j=0 表示没, 1 表示有 )... 的 x = M*v1 + v2 最小
其实对于j的设法还可以设成i点有没有放灯的...可能写起来没那么优美
而且,设父亲的话,转移比较好想出来...
对于在i点不放灯的情况。。其孩子必须放灯。。这是没有异议的。
然后对于i点放灯的话,,孩子是可放可不放的,,,
然而我们的目的只是取 min( dp[v][0] , dp[v][1] ) 罢了~~
根本无需枚举所有组合方式~
#include <bits/stdc++.h>using namespace std;const int N = 1010;int dp[N][2];int n , m ;vector<int>g[N];int DP( int u , int j , int fa ){ if( dp[u][j] != -1 ) return dp[u][j]; int& ans = dp[u][j]; ans = 2000; for( int i = 0 ; i < g[u].size() ; ++i ){ int v = g[u][i]; if( v == fa ) continue ; ans += DP( v , 1 , u ); } if( fa >= 0 && !j ) ans++; if( j || fa < 0 ){ int sum = 0 ; for( int i = 0 ; i < g[u].size(); ++i ){ int v = g[u][i]; if( v == fa ) continue ; sum += DP( v , 0 , u ) ; } if( fa >= 0 ) sum++ ; ans = min( ans ,sum ) ; } return ans;}void run(){ int u , v ; cin >> n >> m ; for( int i = 0 ; i < n ; ++i )g[i].clear(); memset( dp , -1 , sizeof dp ); for( int i = 0 ; i < m ; ++i ){ cin >> u >> v ; g[u].push_back(v); g[v].push_back(u); } int ans = 0 ; for( int i = 0 ; i < n ; ++i ){ if( dp[i][0] == -1 ) ans += DP( i , 0 , -1 ); } cout << ( ans / 2000 ) << ‘ ‘ << ( m - ans % 2000 ) <<‘ ‘<< ( ans % 2000 ) << endl;}int main(){ #ifdef LOCAL freopen("in.txt","r",stdin); #endif ios::sync_with_stdio(false); int _ ; cin >> _ ; while( _-- )run();}
UVA 10859 Placing Lampposts