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
     
  • 相关阅读:
    【Leetcode】23. Merge k Sorted Lists
    【Leetcode】109. Convert Sorted List to Binary Search Tree
    【Leetcode】142.Linked List Cycle II
    【Leetcode】143. Reorder List
    【Leetcode】147. Insertion Sort List
    【Leetcode】86. Partition List
    jenkins 配置安全邮件
    python 发送安全邮件
    phpstorm 同步远程服务器代码
    phpUnit 断言
  • 原文地址:https://www.cnblogs.com/Doggu/p/bzoj3654.html
Copyright © 2011-2022 走看看