51NOD 1640 天氣晴朗的魔法(二分+最大生成樹)

題目鏈接:點擊打開鏈接

思路:

我們二分最大的邊, 這顯然是符合二分性質的, 然後使得邊權和最大用最大生成樹就行了。

細節參見代碼:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <ctime>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const double eps = 1e-6;
const double PI = acos(-1);
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 3e5 + 10;
int T,n,m,p[maxn],x[maxn];
int _find(int x) { return p[x] == x ? x : p[x] = _find(p[x]); }
struct node {
    int a, b, c;
    node(int a=0, int b=0, int c=0):a(a), b(b), c(c) {}
    bool operator < (const node& rhs) const {
        return c < rhs.c;
    }
}e[maxn];
bool ok(int mid) {
    int cnt = 1;
    for(int i = 1; i <= n; i++) p[i] = i;
    for(int i = 1; i <= m && e[i].c <= mid; i++) {
        int x = _find(e[i].a);
        int y = _find(e[i].b);
        if(x != y) {
            p[x] = y;
            ++cnt;
        }
        if(cnt >= n) break;
    }
    return cnt >= n;
}
ll cal(int mid) {
    ll ans = 0;
    int cnt = 1;
    for(int i = 1; i <= n; i++) p[i] = i;
    for(int i = m; i >= 1; --i) {
        if(e[i].c > mid) continue;
        int x = _find(e[i].a);
        int y = _find(e[i].b);
        if(x != y) {
            p[x] = y;
            cnt++;
            ans += (ll)e[i].c;
        }
        if(cnt >= n) break;
    }
    return ans;
}
int main() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; i++) {
        scanf("%d%d%d", &e[i].a, &e[i].b, &e[i].c);
    }
    sort(e+1, e+m+1);
    int cnt = 0;
    for(int i = 1; i <= m; i++) {
        x[cnt++] = e[i].c;
    }
    cnt = unique(x, x+cnt) - x;
    int l = 0, r = cnt-1, mid;
    while(r > l) {
        mid = (l + r) >> 1;
        if(ok(x[mid])) r = mid;
        else l = mid+1;
    }
    printf("%lld\n", cal(x[l]));
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章