• 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
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    编写 iPhone Friendly 的 Web 应用程序
    WebService的安全性讨论【身份识别】
    使用InstallShield系统变量的缺省值
    数据库用户操作相关
    TFS2010安装
    微软实验虚拟机下载地址
    生成18位不重复的ID
    Linux 账户 帐户管理 文件权限 权限管理
    Chrome 插件开发
    Ubuntu 环境变量 设置
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13640019.html
Copyright © 2020-2023  润新知