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

    HINT

    原数据出错,现已更新 by liutian,但未重测---2016.6.24

    正解:二分+$kruskal$。

    简直是一道神题啊。。

    如果直接$kruskal$求最小生成树,是无法保证白边数量的,那么我们考虑如果改变白边的数量。我们可以把白边全部都加上一个权值,也就是我们二分的值,然后跑最小生成树,同时记录白边数量。当白边数量$>=need$时,$l=mid+1$,否则$r=mid-1$,更新答案就是这棵生成树的权值和减去所有白边的增量。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <cstdio>
     7 #include <vector>
     8 #include <cmath>
     9 #include <queue>
    10 #include <stack>
    11 #include <map>
    12 #include <set>
    13 #define inf (1<<30)
    14 #define N (200010)
    15 #define il inline
    16 #define RG register
    17 #define ll long long
    18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    19 
    20 using namespace std;
    21 
    22 struct edge{ int u,v,w,c; }g[N];
    23 
    24 int fa[N],n,m,ans,need;
    25 
    26 il int gi(){
    27     RG int x=0,q=1; RG char ch=getchar();
    28     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    29     if (ch=='-') q=-1,ch=getchar();
    30     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    31     return q*x;
    32 }
    33 
    34 il int cmp(const edge &a,const edge &b){
    35     if (a.w==b.w) return a.c<b.c; return a.w<b.w;
    36 }
    37 
    38 il int find(RG int x){ return fa[x]==x ? x : fa[x]=find(fa[x]); }
    39 
    40 il int check(RG int key){
    41     for (RG int i=1;i<=m;++i) if (!g[i].c) g[i].w+=key;
    42     sort(g+1,g+m+1,cmp); RG int tt=0,sum=0;
    43     for (RG int i=1;i<=n;++i) fa[i]=i;
    44     for (RG int i=1,x,y,k=0;i<=m;++i){
    45     x=find(g[i].u),y=find(g[i].v);
    46     if (x!=y) ++k,fa[x]=y,tt+=g[i].c^1,sum+=g[i].w;
    47     if (k==n-1) break;
    48     }
    49     if (tt>=need) ans=sum-tt*key;
    50     for (RG int i=1;i<=m;++i) if (!g[i].c) g[i].w-=key;
    51     return tt>=need;
    52 }
    53 
    54 il void find(){
    55     RG int l=-100,r=100,mid;
    56     while (l<=r){
    57     mid=(l+r)>>1;
    58     if (check(mid)) l=mid+1; else r=mid-1;
    59     }
    60     return;
    61 }
    62 
    63 il void work(){
    64     n=gi(),m=gi(),need=gi();
    65     for (RG int i=1;i<=m;++i)
    66     g[i].u=gi()+1,g[i].v=gi()+1,g[i].w=gi(),g[i].c=gi();
    67     find(); printf("%d
    ",ans); return;
    68 }
    69 
    70 int main(){
    71     File("tree");
    72     work();
    73     return 0;
    74 }
  • 相关阅读:
    (数据科学学习手札33)基于Python的网络数据采集实战(1)
    (数据科学学习手札32)Python中re模块的详细介绍
    (数据科学学习手札31)基于Python的网络数据采集(初级篇)
    (数据科学学习手札30)朴素贝叶斯分类器的原理详解&Python与R实现
    (数据科学学习手札29)KNN分类的原理详解&Python与R实现
    (数据科学学习手册28)SQL server 2012中的查询语句汇总
    牛客3 F/G 牛牛的Link Power |线段树区间修改
    牛客2-H施魔法|线段树优化dp,维护区间最小值
    2020牛客寒假算法基础集训营1
    友情链接
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6979712.html
Copyright © 2011-2022 走看看