首页 > 代码库 > BZOJ 1196 二分答案+并查集

BZOJ 1196 二分答案+并查集

http://www.lydsy.com/JudgeOnline/problem.php?id=1196

题目大意:n个城市,m-1条路,每条路有一级公路和二级公路之分,你要造n-1条路,一级公路至少要造k条,求出所造路的最大所需的val的最小值.

思路:首先我们一定要明确这个不是一题求所有花费的最小值的问题。然后我们只要二分答案就可以了。最后注意一下条件的拜访即可。

技术分享
//看看会不会爆int!数组会不会少了一维!//取物问题一定要小心先手胜利的条件#include <bits/stdc++.h>using namespace std;#define LL long long#define ALL(a) a.begin(), a.end()#define pb push_back#define mk make_pair#define fi first#define se secondconst int maxn = 10000 + 5;const int inf = 0x3f3f3f3f;struct Edge{    int u, v, val1, val2;    Edge(int u = 0, int v = 0, int v1 = 0, int v2 = 0): u(u), v(v), val1(v1), val2(v2){}    bool operator < (const Edge &a) const{        if (val1 != a.val1) return val1 < a.val1;        return val2 < a.val2;    }}e[maxn * 2];int n, k, m;int par[maxn];int pfind(int x){    if (par[x] == x) return x;    return par[x] = pfind(par[x]);}bool judge(int midval){    for (int i = 1; i <= n; i++) par[i] = i;    int cnt1 = 0, cnt = 0;    for (int i = 1; i <= m - 1; i++){        Edge a = e[i];        int pu = pfind(a.u), pv = pfind(a.v);        if (pu == pv) continue;        if (a.val1 <= midval) cnt1++, cnt++, par[pu] = pv;        else if (a.val2 <= midval) cnt++, par[pu] = pv;    }    if (cnt == n-1 && cnt1 >= k) return true;    return false;}int main(){    scanf("%d%d%d", &n, &k, &m);    int lb = 0, rb = 30000;    for (int i = 1; i <= m - 1; i++){        int u, v, v1, v2;        scanf("%d%d%d%d", &u, &v, &v1, &v2);        e[i] = Edge(u, v, v1, v2);    }    sort(e + 1, e + m);    while (lb < rb){        int mid = lb + (rb - lb) / 2;        if (judge(mid)){            rb = mid;        }        else {            lb = mid + 1;        }    }    printf("%d\n", lb);    return 0;}/*3 1 31 2 11 42 3 10 2*/
View Code

 

BZOJ 1196 二分答案+并查集