• 洛谷 5540 最小乘积生成树


    题目:传送门

    题意

     

    思路

    图文题解

    将每条边的 a 和 b 看成二维坐标系上的点 (a,b),然后找到这些点中距离 y 轴最近的点(即 x 最小的点) A 和 距离 x 轴最近的点 B(y最小的那个点)。也就是现在我们知道了两个方案 A 和 B,假设现在有一个更优的方案 C,那么 C 在二维坐标系上,要满足在向量 AB 的右边。然后我们接着递归 AC, CB 直到不存在点在 AB 的右边。

    #include <bits/stdc++.h>
    #define LL long long
    #define ULL unsigned long long
    #define mem(i, j) memset(i, j, sizeof(i))
    #define rep(i, j, k) for(int i = j; i <= k; i++)
    #define dep(i, j, k) for(int i = k; i >= j; i--)
    #define pb push_back
    #define make make_pair
    #define INF 0x3f3f3f3f
    #define inf LLONG_MAX
    #define PI acos(-1)
    #define fir first
    #define sec second
    #define lb(x) ((x) & (-(x)))
    using namespace std;
    
    const int N = 2e6 + 5;
    
    int f[N];
    
    struct note {
        int u, v;
        LL a, b, c;
    } a[N];
    
    bool cmp(note a, note b) {
        return a.c < b.c;
    }
    
    pair < LL, LL > ans;
    
    LL ANS = inf;
    
    int n, m;
    
    int Fin(int v) {
        if(f[v] == v) return v;
        return f[v] = Fin(f[v]);
    }
    
    pair < LL, LL > get() { /// 最小生成树
    
        rep(i, 1, n) f[i] = i;
    
        sort(a + 1, a + 1 + m, cmp);
    
        pair < LL , LL > res = make(0, 0);
    
        rep(i, 1, m) {
    
            if(Fin(a[i].u) == Fin(a[i].v)) continue;
    
            res.fir += a[i].a;
    
            res.sec += a[i].b;
    
            f[Fin(a[i].u)] = Fin(a[i].v);
    
        }
    
        if(res.fir * res.sec < ANS || (res.fir * res.sec == ANS && res.fir < ans.fir)) ans = res, ANS = res.fir * res.sec;
    
        return res;
    
    }
    
    void cal(pair < LL, LL > A, pair < LL, LL > B) {
    
        rep(i, 1, m) a[i].c = (B.fir - A.fir) * a[i].b + (A.sec - B.sec) * a[i].a;
    
        pair < LL, LL > C = get();
    
        if((B.fir - A.fir) * (C.sec - A.sec) - (B.sec - A.sec) * (C.fir - A.fir) >= 0) return ;
    
        cal(A, C);
    
        cal(C, B);
    
    }
    
    int main() {
    
        scanf("%d %d", &n, &m);
    
        rep(i, 1, m) {
    
            scanf("%d %d %lld %lld", &a[i].u, &a[i].v, &a[i].a, &a[i].b);
    
            a[i].u++; a[i].v++;
    
        }
        rep(i, 1, m) a[i].c = a[i].a;
    
        pair < LL, LL > A = get();
    
        rep(i, 1, m) a[i].c = a[i].b;
    
        pair < LL, LL > B = get();
    
        cal(A, B);
    
        printf("%lld %lld
    ", ans.fir, ans.sec);
    
        return 0;
    
    }

     

  • 相关阅读:
    2015多校1006.First One
    2015多校.MZL's endless loop(欧拉回路的机智应用 || 构造)
    LUXURY 8
    矩阵快速幂模板
    博弈入门
    cf558c(bfs)
    LUXURY 7
    dfs序 + RMQ = LCA
    双端队列
    UVa-401 Palindromes
  • 原文地址:https://www.cnblogs.com/Willems/p/12830359.html
Copyright © 2020-2023  润新知