• P3623 [APIO2008]免费道路


    P3623 [APIO2008]免费道路

    WQS二分题解。(好像可以不用这个做法)

    就是给每个点随一个权值,然后跑正常的WQS二分。

    (l, r) 可以是浮点数。

    时间 (O(n log^2n))

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <ctime>
    
    using namespace std;
    
    typedef long long ll;
    const ll MAXN = 1e6+10;
    
    ll N, M, K, fa[MAXN], vis[MAXN];
    double ans = 1e99;
    
    struct edge {
        ll x, y, c, id;
        double w;
        friend bool operator < (edge a, edge b) {return a.w == b.w ? a.c < b.c : a.w < b.w;}
    } E[MAXN];
    
    bool cmp(edge, edge);
    ll check(double);
    ll find_(ll);
    
    int main() {
    	srand(time(0));
        scanf("%lld%lld%lld", &N, &M, &K);
        for (ll i = 1; i <= M; i++) {
            scanf("%lld%lld%lld", &E[i].x, &E[i].y, &E[i].c);
            E[i].w = rand() % M; E[i].id = i;
        }
        double l = -1e8, r = 1e8;
        while (r - l >= 1e-5) {
            double mid = (l + r) / 2.0;
            ll num = check(mid);
            if (num > K) l = mid + 1;
            else if (num == K) {l = mid + 1, ans = mid; break;} 
            else r = mid - 1;
        }
        if (ans == 1e99) {
        	puts("no solution");
    		return 0;
    	}
    	sort(E+1, E+M+1, cmp);
        for (ll i = 1; i <= M; i++)
            if (vis[i])
                printf("%lld %lld %lld
    ", E[i].x, E[i].y, E[i].c);
        return 0;
    }
    
    bool cmp(edge a, edge b) {return a.id < b.id;}
    
    ll check(double now) {
        for (ll i = 1; i <= N; i++) fa[i] = i;
        for (ll i = 1; i <= M; i++) {
    		if (!E[i].c) E[i].w += now;
    		vis[i] = 0;
    	}
        sort(E+1, E+M+1);
        ll ret = 0;
        for (ll i = 1, cnt = 1; cnt < N && i <= M; i++) {
            ll fx = find_(E[i].x), fy = find_(E[i].y);
            if (fx != fy) {
                cnt++;
                fa[fx] = fy;
                ret += (E[i].c == 0 ? 1 : 0);
                vis[E[i].id] = 1;
            }
        }
        for (ll i = 1; i <= M; i++) if (!E[i].c) E[i].w -= now;
        return ret;
    }
    
    ll find_(ll x) {return fa[x] == x ? x : fa[x] = find_(fa[x]);}
    
  • 相关阅读:
    nxn随机矩阵乘以概率向量依旧是概率向量
    关于飞行器姿态计算
    两矩阵相乘后的秩
    关于矩阵A*b=A*c 中b是否等于c
    5.5节24题
    推论5.2.5
    js中function参数默认值
    陈经纶学校分析数据导出情况
    支付宝申请
    外国javascript资源搜索
  • 原文地址:https://www.cnblogs.com/Gensokyo-Alice/p/13904550.html
Copyright © 2020-2023  润新知