ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

BZOJ2654 tree

2019-07-12 18:52:56  阅读:184  来源: 互联网

标签:BZOJ2654 int tree 白边 mid read need include


一开始打了个贪心,求最小生成树,白边多就把权值最大的白边干掉,白边少就把权值最大的黑边干掉,因为数据肯定有解嘛。结果大点TLE,小点只过了一个。事实证明,贪心有时真的不能瞎用。

其实这个二分还是挺有道理的,给白边加权值,则入选白边会减少,给白边减权值,则入选白边增加,二分枚举这个权值,白边多了则向大枚举,白边少了则向小枚举,思路蛮简单的。

剩下的就是二分的细节了。试了无数遍,终于找到了最合适的二分方法,而且等号最好放在大于号那里,因为恰好有need条白边以后ans还不一定最优,应该尝试着在白边不变的基础上,把更优秀的黑边加进来,需要把白边排斥一下。

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
struct EDGE{
    int st,ed,nex,val,col;
}edge[2005000];int num,first[500050];
int read(){
    int sum=0,f=1;char x=getchar();
    while(x<'0'||x>'9'){
        if(x=='-') f=-1;
        x=getchar();
    }while(x>='0'&&x<='9'){
        sum=sum*10+x-'0';
        x=getchar();
    }return sum*f;
}
int n,m,need,ans,ans2,fa[500500];
void add(int st,int ed,int val,int col){
    edge[++num].st=st;
    edge[num].ed=ed;
    edge[num].val=val;
    edge[num].col=col;
    edge[num].nex=first[st];
    first[st]=num;
}
bool camp(EDGE a,EDGE b){
    if(a.val==b.val) return a.col>b.col;
    return a.val<b.val;
}
int get(int x){
    return x==fa[x]?x:fa[x]=get(fa[x]);
}
bool check(int x){
//    cout<<"mid="<<x<<endl;
    int color=0,sum=0;
    ans=0;
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1;i<=num;i++) 
        if(edge[i].col) edge[i].val+=x;
    sort(edge+1,edge+1+num,camp);
    for(int i=1;i<=num;i++){
        int x=edge[i].st,y=edge[i].ed;
        x=get(x);y=get(y);
        if(x==y) continue;
        fa[x]=y;
        color+=edge[i].col;
        ans+=edge[i].val;
        sum++;
        if(sum==n-1) break;
    }
    for(int i=1;i<=num;i++)
        if(edge[i].col) edge[i].val-=x;
/*    cout<<color<<" "<<endl;
    for(int i=1;i<=num;i++){
        cout<<edge[i].val<<" ";
    }cout<<endl;*/
//    fgetc(stdin);
    return color>=need;
}
int main(){
    n=read();m=read();need=read();
    for(int i=1;i<=m;i++){
        int st=read(),ed=read(),val=read(),col=read();
        add(st+1,ed+1,val,col^1);
    }
    int l=-102,r=102;
    while(l<r){
    //    cout<<l<<" "<<r<<endl;
        int mid=l+r>>1;
        if(check(mid)){ 
            l=mid+1;
            ans2=ans-need*mid;
        }
        else r=mid;

    }printf("%d",ans2);
    return 0;
}
View Code

 

标签:BZOJ2654,int,tree,白边,mid,read,need,include
来源: https://www.cnblogs.com/Yu-shi/p/11177856.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有