UVA10859 Placing Lampposts

题意:给一个无向无环图(n<1000),在尽量少的节点上放灯,使得所有边都被照亮,灯可以照亮相邻的边,在灯数最小的前提下,使得被两盏灯照亮的边最多,输出灯数以及被两盏灯照亮的边数,及剩下的边数

题解:树形dp,树上的优化,灯选或不选dp[i][0]和dp[i][1],主要的问题在于多个限制条件,这里就有一个小技巧,可以把两个限制条件变为一个数,b = M*a+c,a是灯的数量,c是一盏灯的数量,M是一个很大的数,那么这样a就占据主导作用,接下来就是树形dp具体看代码,注意初始化

#include <bits/stdc++.h>
#define ll long long
#define maxn 1100
#define M 2000
using namespace std;
vector<int >G[maxn];
int dp[maxn][2], dir[maxn];
int dfs(int x){
    dir[x] = 1;
    dp[x][0] = 0;
    dp[x][1] = M;
    for(int i=0;i<G[x].size();i++){
        int u = G[x][i];
        if(dir[u]) continue;
        dfs(u);
        dp[x][1] += min(dp[u][1], dp[u][0]+1);
        dp[x][0] += dp[u][1]+1;
    }
    return min(dp[x][0], dp[x][1]);
}
int main(){
    int T, n, m, a, b, ans;
    scanf("%d", &T);
    while(T--){
        memset(dir, 0, sizeof(dir));
        ans = 0;
        scanf("%d%d", &n, &m);
        for(int i=0;i<n;i++) G[i].clear();
        for(int i=0;i<m;i++){
            scanf("%d%d", &a, &b);
            G[a].push_back(b);
            G[b].push_back(a);
        }
        for(int i=0;i<n;i++)
            if(!dir[i])
                ans += dfs(i);
        printf("%d %d %d\n", ans/M, m-ans%M, ans%M);
    }
    return 0;
}

 

posted on 2017-09-03 14:53  2855669158  阅读(122)  评论(0编辑  收藏  举报

导航