uva10859 - Placing Lampposts

来源:互联网 发布:黑龙江省人工智能学会 编辑:程序博客网 时间:2024/06/01 10:50

题意:
有n个点m条边的无向无环图,在尽量少的点放灯,让所有边都能被照,且尽量多的边同时被找到。
思路:
题目有两个地方要控制,a:一个是放灯的点——要尽量少,b:第二个是被两盏灯照到的边—-尽量多。
学到一个小技巧,就是将第二问题转为b:被一盏灯照到的边 — 尽量少,所求即x=Ma+b最小,M为一个比a,b大得多的数。
然后就是控制x使其最小了。
代码如下:

#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;const int N = 1005;const int M = 2000;int vis[N],  dp[N][2];vector <int> ege[N];int n, m;void dfs(int u) {    vis[u] = 1;    dp[u][0] = 0;//u点不放灯    dp[u][1] = M;//u点放灯    for (int i = 0; i < ege[u].size(); i++) {        int v = ege[u][i];        if (vis[v])            continue;        dfs(v);        dp[u][0] += dp[v][1] + 1;        if (dp[v][0] < dp[v][1])            dp[u][1] += dp[v][0] + 1;        else            dp[u][1] += dp[v][1];    }}int main() {     int cas;    scanf("%d", &cas);    while (cas--){        memset(dp, 0, sizeof(dp));        memset(vis, 0, sizeof(vis));        for (int i = 0; i < n; i++)            ege[i].clear();        scanf("%d%d", &n, &m);        int u, v;        for (int i = 0; i < m; i++) {            scanf("%d%d", &u, &v);            ege[u].push_back(v);            ege[v].push_back(u);        }        int ans = 0;        for (int i = 0; i < n; i++) {            dfs(i);            ans += min(dp[i][0], dp[i][1]);        }        printf("%d %d %d\n", ans / M, m - (ans%M), ans%M);    }    return 0;}
0 0