zoukankan      html  css  js  c++  java
  • 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

    Sample Output

    2

     

    二分+最小生成树,一开始真的很难想。就是二分一个值,给所有的白色边加上这个值,跑最小生成树保证白边数刚好是need

    其中二分中的细节需要注意一下。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <queue>
    #include <stack>
    #include <vector>
    using namespace std;
    #define MAXN 100010
    #define INF 2147483647
    #define MOD 10000007
    #define LL long long
    #define in(a) a=read()
    #define REP(i,k,n) for(int i=k;i<=n;i++)
    #define DREP(i,k,n) for(int i=k;i>=n;i--)
    #define cl(a) memset(a,0,sizeof(a))
    inline int read(){
        int x=0,f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
        return x*f;
    }
    inline void out(int x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) out(x/10);
        putchar(x%10+'0');
    }
    int n,m,need;
    int sum,num;
    int ans;
    int f[MAXN];
    int a[MAXN],b[MAXN],w[MAXN],c[MAXN];
    struct node{
        int a,b,w,c;
    }l[MAXN];
    int getf(int k){
        if(f[k]==k)  return k;
        return f[k]=getf(f[k]);
    }
    bool cmp(node x,node y){
        if(x.w==y.w)  return x.c<y.c;
        return x.w<y.w;
    }
    bool check(int k){
        sum=0;
        num=0;
        REP(i,1,n)  f[i]=i;
        REP(i,1,m){
            l[i].a=a[i];
            l[i].b=b[i];
            l[i].c=c[i];
            l[i].w=w[i];
            if(l[i].c==0)  l[i].w+=k;
        }
        sort(l+1,l+m+1,cmp);
        for(int i=1;i<=m;i++){
            int x=getf(l[i].a),y=getf(l[i].b);
            if(x!=y){
                f[y]=x;
                sum+=l[i].w;
                if(!l[i].c)  num++;
            }
        }
        if(num>=need)  return true;
        return false;
    }
    int main(){
        in(n);in(m);in(need);
        REP(i,1,m){
            in(a[i]);in(b[i]);in(w[i]);in(c[i]);
            a[i]++;
            b[i]++;
        }
        int left=-10010,right=10010;
        while(left<=right){
            int mid=(right+left)>>1;
            if(check(mid)){
                left=mid+1;    
                ans=sum-mid*need;
            }
            else right=mid-1;
        }
        cout<<ans;
        return 0;
    }
     
  • 相关阅读:
    【mysql5.6】数据类型
    【leetcode】Multiply Strings(middle)
    创建JDBC模板简化代码、JDBC应用的事务管理以及连接池的作用
    IE8.0登录Oracle EBS后报Oracle error 1403错
    三联动 支持ie6,ie7 省,市,区
    任正非最新訪谈: 假设企业收留这类人, 距离死亡就不远了
    向量空间模型实现文档查询(Vector Space Model to realize document query)
    前端开发的经验
    《大话操作系统——做坚实的project实践派》(7)
    【整理】nand相关
  • 原文地址:https://www.cnblogs.com/jason2003/p/9636891.html
Copyright © 2011-2022 走看看