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
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    Java回顾之Spring基础
    Java回顾之ORM框架
    Java回顾之JDBC
    Java回顾之一些基础概念
    Java回顾之反射
    Java回顾之序列化
    platform_device与platform_driver
    DB9 公头母头引脚定义及连接
    浅谈UML的概念和模型之UML九种图
    为Windows 7的winsxs目录瘦身,谨慎。
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13640019.html
Copyright © 2011-2022 走看看