uva10859 - Placing Lampposts

题意:
有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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值