zoukankan      html  css  js  c++  java
  • BZOJ 2654 tree

    2654: 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条白色边,然后做最小生成树。平常,最小生成树是相对一定的。怎么办呢?

      注意到白边的优先级可以变化(排序时加减“虚”边权,统计时不加入),且存在着优先级与选取边数的单调性。我们让白边公平竞争,集体“虚”边权加减,二分其值([-105,105]),每一次再kruscal,看选取边数。最后输出结果。

      所以说,复杂度是二分O(lg n)*MST.O(nlg n)。

      

     1 /**************************************************************
     2     Problem: 2654
     3     User: Doggu
     4     Language: C++
     5     Result: Accepted
     6     Time:1520 ms
     7     Memory:3164 kb
     8 ****************************************************************/
     9  
    10 #include <cstdio>
    11 #include <algorithm>
    12 template<class T>inline void readin(T &res) {
    13     static char ch;T flag=1;while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;
    14     res=ch-48;while((ch=getchar())>='0'&&ch<='9')res=(res<<1)+(res<<3)+ch-48;res*=flag;
    15 }
    16 const int N = 100000+10;
    17 const int M = 100000+10;
    18 struct Edge {int u, v, w, col, add;}edges[M];
    19 bool operator<(Edge a,Edge b) {return a.w+a.add<b.w+b.add;}
    20 int n, m, need, fa[N];
    21 int find(int x) {
    22     if(fa[x]==x) return x;
    23     return fa[x]=find(fa[x]);
    24 }
    25 int main() {
    26     readin(n);readin(m);readin(need);
    27     for( int i = 1; i <= m; i++ ) {
    28         readin(edges[i].u);readin(edges[i].v);
    29         readin(edges[i].w);readin(edges[i].col);
    30     }
    31     int lf=-105, rg=105, ans=0;
    32     while(lf<=rg) {
    33         int mid=(lf+rg)>>1, k=0, tot=0;
    34         for( int i = 1; i <= m; i++ ) if(!edges[i].col) edges[i].add=mid;
    35         for( int i = 0; i < n; i++ ) fa[i]=i;
    36         std::sort(edges+1,edges+m+1);
    37         for( int i = 1; i <= m; i++ ) {
    38             if(find(edges[i].u)!=find(edges[i].v)) {
    39                 if(!edges[i].col) k++;
    40                 tot+=edges[i].w;
    41                 fa[fa[edges[i].u]]=edges[i].v;
    42             }
    43         }
    44         if(k>=need) ans=tot, lf=mid+1;
    45         else rg=mid-1;
    46     }
    47     printf("%d
    ",ans);
    48     return 0;
    49 }
    二分+MST
     
  • 相关阅读:
    python学习第四天 --字符编码 与格式化及其字符串切片
    Lambda表达式 之 C#
    python学习第三天 --布尔类型
    深入理解正则表达式
    《你不知道的JavaScript》第一部分:作用域和闭包
    jquery的extend和fn.extend
    HttpModule与HttpHandler详解
    jQuery分析(2)
    jQuery分析(1)
    jQuery源码中的“new jQuery.fn.init()”什么意思?
  • 原文地址:https://www.cnblogs.com/Doggu/p/bzoj3654.html
Copyright © 2011-2022 走看看