Codeforces Round #441 Div. 1 F. Royal Questions

链接

http://codeforces.com/contest/875/problem/F

题意

给n个白点,m个黑点,其中第i个黑点和两个白点有边权为 wi 的边,求这个二分图的所有匹配中权值最大的匹配,输出最大的权值。

思路

贪心,之前自己写了一个按边贪心的,结果很容易就wa了 QAQ,看了题解发现要按点来贪心。

给黑点按权值从大到小排序,遍历每个黑点,一个黑点会和两个白点连边,不考虑这个黑点和哪个白点连边,而是把这两个白点缩成一个点,这样这个黑点就一定从两个白点中拿走了一个点,留下了一个点。如果拿到某个黑点只与一个缩点后的白点连边,那么这个黑点只能和这个白点连边,把这个白点标记为不能和其它黑点连边了就好。

代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 2e5 + 5;
struct Node {
  int u, v, w;
  bool operator<(const Node &r) {
    return w > r.w;
  }
};
int n, m;
int pa[N];
bool full[N];
Node nodes[N];
int findset(int x) {
  if (pa[x] == x) return x;
  pa[x] = findset(pa[x]);
  return pa[x];
}
int main() {
  while (~scanf("%d%d", &n, &m)) {
    for (int i = 0; i < m; ++i) scanf("%d%d%d", &nodes[i].u, &nodes[i].v, &nodes[i].w);
    sort(nodes, nodes + m);
    for (int i = 1; i <= n; ++i) pa[i] = i;
    for (int i = 1; i <= n; ++i) full[i] = false;
    int ans = 0, u, v;
    for (int i = 0; i < m; ++i) {
      u = findset(nodes[i].u);
      v = findset(nodes[i].v);
      if (u == v && !full[u]) {
        ans += nodes[i].w;
        full[u] = true;
      }
      else if (u != v && (!full[u] || !full[v])) {
        ans += nodes[i].w;
        pa[u] = v;
        full[v] |= full[u];
      }
    }
    printf("%d\n", ans);
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值