(图论)汤圆防漏理论

题目链接

题意

\(题目让我们找到一个最大值k,使得每删去一个点v,都使得删去点的边权和不超过k.\)

思路

\(容易想到一定是优先删去边权和最小的最好\)

\(所以这里要始终能找到一个最小边权之和的点,用set就很方便\)

\(我们先把所有点放入set,每次拿出边权和最小的点,用它去更新其他点的边权和\)

代码
#include <bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);
inline int lowbit(int x) { return x & (-x); }
#define ll long long
#define ull unsigned long long
#define pb push_back
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define VIT vector<int>
#define x first
#define y second
#define inf 0x3f3f3f3f
const int N = 1e5 + 7, M = 2 * N;
bool st[N];
vector<PII> v[N];
ll sum[N];
set<pair<ll, int>> s;

int main() {
    IO;
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int _;
    cin >> _;
    while (_--) {
        s.clear();
        int n, m;
        cin >> n >> m;
        for (int i = 1; i <= n; ++i) {
            st[i] = 0;
            sum[i] = 0;
            v[i].clear();
        }
        while (m--) {
            int a, b, c;
            cin >> a >> b >> c;
            v[a].pb({b, c});
            v[b].pb({a, c});
            sum[a] += c;
            sum[b] += c;
        }
        for (int i = 1; i <= n; ++i) 
            s.insert({sum[i], i});
        ll ans = 0;
        while (s.size()) {
            auto t = s.begin();
            s.erase(s.begin());
            ans = max(ans, (*t).x);
            int ver = (*t).y;
            st[ver] = 1;
            for (int i = 0; i < v[ver].size(); ++i) {
                int j = v[ver][i].x;
                if (st[j]) continue;
                s.erase({sum[j], j});
                sum[j] -= v[ver][i].y;
                s.insert({sum[j], j});
            }
        }
        cout << ans << '\n';
    }
    return 0;
}

posted @ 2021-02-28 12:46  phr2000  阅读(66)  评论(0编辑  收藏  举报