zoukankan      html  css  js  c++  java
  • BZOJ2654 tree(wqs二分)

    有关于wqs二分的问题,一般伴随着选指定个数的数量,且数量选取的多少和方法都会影响答案的一种问题。

    这种问题一般都具有凸性,也就是斜率单增单减,这样我们就可以套上wqs二分来优化。

    这基于的原理可以观看wqs本人的论文。

    对于这题,我们发现选取白边的数量对答案是由影响的,也可以证明他确实具有凸性。

    我们二分权值,对于每个白边都加上这个权值,之后做一遍最小生成树。如果使用的白边数量不够,说明我们需要往左边二分,也就是我们希望白边的个数增多。

    反之就往右边二分,但是很多题目这样二分是可能出不了结果的,这是因为,我们附加的权值即使变化1,白边数量不一定变化1,因为我们可能在相同权值的白边和黑边上选择了黑边。

    因此我们考虑排序,将白边先选,这样我们肯定可以刚好变化成要求数量。很多题目都要像这样附加一个条件。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<ll,ll> pll;
    const int N=2e6+10;
    const int M=2e6+10;
    const int inf=0x3f3f3f3f;
    int p[N],n,m,k;
    ll ans;
    struct node{
        int a,b,c,id;
    }e[N],s[N];
    bool cmp(node a,node b){
        if(a.c==b.c)
            return a.id<b.id;
        else
            return a.c<b.c;
    }
    int find(int x){
        if(p[x]!=x){
            p[x]=find(p[x]);
        }
        return p[x];
    }
    int check(int x){
        int i;
        int tot=0;
        int cnt=0;
        ans=0;
        for(i=1;i<=m;i++){
            s[i]=e[i];
            if(e[i].id==0)
                s[i].c+=x;
        }
        for(i=1;i<=n;i++)
            p[i]=i;
        sort(s+1,s+1+m,cmp);
        for(i=1;i<=m;i++){
            int pa=find(s[i].a);
            int pb=find(s[i].b);
            if(pa!=pb){
                tot++;
                if(!s[i].id)
                    cnt++;
                p[pa]=pb;
                ans+=s[i].c;
            }
            if(tot==n-1)
                break;
        }
        return cnt>=k;
    }
    int main(){
        ios::sync_with_stdio(false);
        int i;
        cin>>n>>m>>k;
        for(i=1;i<=m;i++){
            cin>>e[i].a>>e[i].b>>e[i].c>>e[i].id;
            e[i].a++;
            e[i].b++;
        }
        int l=-100,r=100;
        int us=0;
        while(l<r){
            int mid=l+r+1>>1;
            if(check(mid)){
                l=mid;
            }
            else
                r=mid-1;
        }
        check(l);
        cout<<ans-l*k<<endl;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    二分+RMQ/双端队列/尺取法 HDOJ 5289 Assignment
    思维题 HDOJ 5288 OO’s Sequence
    树形DP Codeforces Round #135 (Div. 2) D. Choosing Capital for Treeland
    最大流增广路(KM算法) HDOJ 1853 Cyclic Tour
    最大流增广路(KM算法) HDOJ 1533 Going Home
    最大流增广路(KM算法) HDOJ 2255 奔小康赚大钱
    Complete the Word CodeForces
    Gadgets for dollars and pounds CodeForces
    Vasya and Basketball CodeForces
    Carries SCU
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13640019.html
Copyright © 2011-2022 走看看