二分+最小生成树【bzoj2654】: tree

2654: tree

给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有need条白色边的生成树。

题目保证有解。

二分答案,然后跑最小生成树判断。

注意优先跑白色边。

code:

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int wx=500017;

inline int read(){
    int sum=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
    return sum*f;
}

int fa[wx];
int n,m,k,tot,ans;

struct node{
    int x,y,d,flag;
    friend bool operator < (const node & a,const node & b){
        return a.d<b.d;
    }
}t[wx*2];

int find(int x){
    if(x==fa[x])return x;
    return fa[x]=find(fa[x]);
}

bool ok(int now){
    for(int i=1;i<=n;i++)fa[i]=i;
    int sum=0,tmp=0;

    for(int i=1;i<=m;i++){
        if(t[i].flag)continue;
        int fx=find(t[i].x); int fy=find(t[i].y);
        if(fx==fy)continue;
        if(t[i].flag==0&&tmp>=k)continue;
        sum+=t[i].d; fa[fx]=fy;
        if(t[i].flag==0)tmp++;
    }
    for(int i=1;i<=m;i++){
        int fx=find(t[i].x); int fy=find(t[i].y);
        if(fx==fy)continue;
        if(t[i].flag==0&&tmp>=k)continue;
        sum+=t[i].d; fa[fx]=fy;
        if(t[i].flag==0)tmp++;
    }
    return sum<=now&&tmp>=k;
}

int main(){
    n=read(); m=read(); k=read();
    for(int i=1;i<=m;i++){
        int x,y,z,c;
        x=read(); y=read(); z=read(); c=read();
        x++; y++;
        t[i].x=x; t[i].y=y; t[i].d=z; t[i].flag=c;
        tot+=z;
    }
    sort(t+1,t+1+m);
    int l=0,r=tot;
    while(l<=r){
        int mid=l+r>>1;
        if(ok(mid))ans=mid,r=mid-1;
        else l=mid+1;
    }
    printf("%d\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/wangxiaodai/p/9857971.html

时间: 2024-08-05 09:40:57

二分+最小生成树【bzoj2654】: tree的相关文章

【BZOJ2654】tree 二分+最小生成树

[BZOJ2654]tree Description 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. Input 第一行V,E,need分别表示点数,边数和需要的白色边数. 接下来E行,每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色). Output 一行表示所求生成树的边权和. V<=50000,E<=100000,所有数据边权为[1,100]中的正整数. Sample Input 2 2 1

BZOJ 2654 tree 二分+最小生成树

题目大意 给出一些边,每个边有一个边权和颜色.现在要求出最小边权有need个白边的生成树.输出这个边权. 思路 在白边上加一个权值,这样就可以人为的改变白边出现在最小生成树.这个东西显然可以二分.之后取一下最小值就可以了. CODE #define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #def

Two Famous Companies 【二分+最小生成树】

Problem DescriptionIn China, there are two companies offering the Internet service for the people from all cities: China Telecom and China Unicom. They both are planning to build cables between cities. Obviously, the government wants to connect all t

BZOJ2654 tree

Description 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. Input 第一行V,E,need分别表示点数,边数和需要的白色边数. 接下来E行,每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色). Output 一行表示所求生成树的边权和. V<=50000,E<=100000,所有数据边权为[1,100]中的正整数. Sample Input 2 2 1 0 1 1 1 0 1 2 0

POJ 2728 二分+最小生成树

题意:给n个点,可以将每个点的x,y的欧几里得距离(就是坐标系里两点距离公式)看作距离,z的差值即为费用差,求的是所有最小生成树中的min(边费用和/边距离和). 思路:其实挑战P143有类似的列题,用的是二分枚举答案的方法,只不过不是树.这一题仅仅需要将题给图找出最小生成树,然后同样枚举即可. 虽然网上有许多高级的名词什么最优比率xxx之类的..以及迭代的方法,不过我认为用二分也很好,易于想到也可以加深理解. 1 #include <iostream> 2 3 #include <st

POJ2349:Arctic Network(二分+最小生成树)

Arctic Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 28311   Accepted: 8570 题目链接:http://poj.org/problem?id=2349 Description: The Department of National Defence (DND) wishes to connect several northern outposts by a wireless net

BZOJ 1196 公路修建问题(二分+最小生成树)

题目要求求出图中的一颗生成树,使得最大的边权最小,且满足一级公路的个数>=k. 考虑二分最大边,问题就变为给出的图的生成树中,是否满足所有的边<=val,且一级公路的个数>=k. 所以我们把边按一级公路权值排序,优先选择能构成生成树的一级公路.这样贪心的构造. # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include &

WQS二分题集

WQS二分,一种优化一类特殊DP的方法. 很多最优化问题都是形如“一堆物品,取与不取之间有限制.现在规定只取k个,最大/小化总收益”. 这类问题最自然的想法是:设f[i][j]表示前i个取j个的最大收益,转移即可.复杂度O(n^2). 那么,如果在某些情况下,可以通过将问题稍作转化,变成一个不强制选k个的DP,而最后DP出来的最优解一定正好选了k个,那么问题就会简化很多. WQS二分就是基于这个思想. 首先考虑建一个二维坐标系,x轴是选的数的个数,y轴是最大收益,如果这个x-y图像有凸性,那么就

带权二分

带权二分 一种二分答案的套路,又叫做DP凸优化,wqs二分. 用来解决一类题目,要求某个要求出现K次,并且,可以很显然的发现,在改变相应权值的时候,对应出现的次数具有单调性.而且很显然,这种题一般满足一定的要求.而且一般权值为整数二分就可以,但是有的题需要实数二分...而且,边界条件通常很麻烦,调起来想摔电脑. 例题时间: BZOJ2654: tree 题目大意:给你一个图,里面有白色边和黑色边,问恰好有k条边白色边的最小生成树 直接贪心法肯定是错误的,因此,我们考虑带权二分. 给定一个选择白色