UVA 10859Placing Lampposts(树上的DP)

来源:互联网 发布:新速特软件站快优影音 编辑:程序博客网 时间:2024/04/29 23:32

动态规矩 简直无所不能 无所不干。


这个题还是比较好想的。  因为是一个无向图。 在递归的过程中 直接从一个点当做树根开始递归下面的树。 对于每个点 方灯 或者不放灯 有两种状态。 对于每一


颗子树都求出最小值 然后往根回。 这样就求出 这颗树的 最小灯数了。


这个题用了一个技巧。   对于 x y  如果要求其最小值 就领 K = x* m + y 求最小值  


在训练之南上 这个题的 代码不好理解。  看了网上的代码


#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<queue>#include<cmath>#include<cstring>using namespace std;typedef long long int64;const int INF = 0x3f3f3f3f;const int MAXN = 1010;vector<int>adj[MAXN];bool vis[MAXN];int n, m;int f[MAXN][2];const int M = 2000;void dfs(int u) {    vis[u] = true;    f[u][0] = 0;    f[u][1] = M;    for(int i = 0; i < adj[u].size(); ++i) {        int v = adj[u][i];        if(vis[v]) continue;        dfs(v);        f[u][0] += f[v][1] + 1;        if (f[v][0] < f[v][1]) {            f[u][1] += f[v][0] + 1;        } else {            f[u][1] += f[v][1];        }    }}int main(){    int nCase;    scanf("%d", &nCase);    while(nCase--) {        scanf("%d%d", &n, &m);        for(int i = 0; i < n; ++i)            adj[i].clear();        for(int i = 0; i < m; ++i) {            int u, v;            scanf("%d%d", &u, &v);            adj[u].push_back(v);            adj[v].push_back(u);        }        memset(vis, 0, sizeof(vis));        int ans = 0;        for(int i = 0; i < n; ++i) if(!vis[i]){            dfs(i);            ans += min(f[i][0], f[i][1]);        }        printf("%d %d %d\n", ans/M, m-(ans%M), ans%M);    }    return 0;}




0 0
原创粉丝点击