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

                          Placing Lampposts

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边被两盏灯照亮的边数要尽量多,输出灯数,两盏照亮的边数,一盏照亮的边数。

题解:

  首先对于每个节点,我们都有取或不取,这个DP就好了,下面是如何保证取优先值方法

取双优值方法:

      考虑要保证a最小的情况下...b最小...那么就是在状态转移过程中保证a是占主体地位的..只有当a相等时..b才发挥作用...这可以联想到两个数比较.

      首先要比最高位..当最高位不相等时..低位如何变换都不能影响到比较结果...

                 那么选取一个尽可能大但又不至于爆int,long long的数M..让在题目范围内..b如何多..都达不到M..那么表示状态下值为a*M+b

                 输出答案时...P/M为第一个最优的...P%M为保证第一个最优下第二个最优

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 1e3+20, M = 30005, mod = 1e9+7, inf = 0x3f3f3f3f;
typedef long long ll;
//不同为1,相同为0
vector<int > G[N];
int n,m,vis[N],T,ans,dp[N][2];
void dfs(int u) {
    dp[u][0] = 0;
    dp[u][1] = M+1;
    vis[u] = 1;
    for(int i=0;i<G[u].size();i++) {
        int to = G[u][i];
        if(vis[to]) continue;
        dfs(to);
        dp[u][0]+=dp[to][1];
        dp[u][1] += min(dp[to][1]-1,dp[to][0]+1);
    }
}
int main() {
    scanf("%d",&T);
    while(T--) {
        for(int i=0;i<N;i++) G[i].clear(), vis[i] = 0;
        scanf("%d%d",&n,&m);
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=m;i++) {
            int a,b;
            scanf("%d%d",&a,&b);
            a++,b++;
            G[a].push_back(b);
            G[b].push_back(a);
        }
        ans = 0;
        for(int i=1;i<=n;i++) {
            if(vis[i]) continue;
            dfs(i);
           dp[i][1]--;
            ans += min(dp[i][0], dp[i][1]);
           // cout<<min(dp[i][0], dp[i][1])<<endl;
        }
        printf("%d %d %d\n",ans/M, m-ans%M, ans%M);
    }
    return 0;
}

 

posted @ 2016-04-04 17:55  meekyan  阅读(279)  评论(0编辑  收藏  举报