• 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

     

    正解:二分答案+最小生成树

    解题报告:

      今天LCF的分治题出了这道农boy题,完全不知道跟分治有什么关系。。。

      题解太神,想通这么搞的目的之后就很简单了。

      首先如果直接做,显然用的白边不一定是要求的值,如果边数多了,那么我们考虑如果所有的白边都增加一个值,显然白边数不会增加,应该会减少。这样就可以使我们确定答案选取了哪些白边。边数少了的话,也是一个道理。所以我们考虑二分答案,增加减少的边权必须在边权范围内(多了没意义)。

      注意一下细节,相等情况下,先选白边,可以证明更优。我是蒟蒻,我不会证。

     1 //It is made by jump~
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <algorithm>
     8 #include <ctime>
     9 #include <vector>
    10 #include <queue>
    11 #include <map>
    12 #include <set>
    13 #ifdef WIN32   
    14 #define OT "%I64d"
    15 #else
    16 #define OT "%lld"
    17 #endif
    18 using namespace std;
    19 typedef long long LL;
    20 const int MAXN = 100011;
    21 const int MAXM = 400011;
    22 int n,m,allow;
    23 int first[MAXN];
    24 int father[MAXN];
    25 int ecnt,cnt;
    26 LL tot;
    27 LL ans;
    28 
    29 struct edge{
    30     int u,v,w;
    31     int flag;
    32 }e[MAXM];
    33 
    34 inline int getint()
    35 {
    36        int w=0,q=0;
    37        char c=getchar();
    38        while((c<'0' || c>'9') && c!='-') c=getchar();
    39        if (c=='-')  q=1, c=getchar();
    40        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
    41        return q ? -w : w;
    42 }
    43 
    44 inline int find(int x){
    45     if(father[x]!=x) father[x]=find(father[x]);
    46     return father[x];
    47 }
    48 
    49 inline bool cmp(edge q,edge qq){ if(q.w==qq.w) return q.flag<qq.flag;  return q.w<qq.w; }
    50 
    51 inline bool check(int x){
    52     for(int i=1;i<=n;i++) father[i]=i;    
    53     for(int i=1;i<=m;i++) if(!e[i].flag) e[i].w+=x;
    54     sort(e+1,e+m+1,cmp);
    55     int r1,r2; cnt=0; tot=0;
    56     for(int i=1;i<=m;i++) {
    57     r1=find(e[i].u); r2=find(e[i].v);
    58     if(r1!=r2) {
    59         father[r2]=r1;
    60         if(!e[i].flag) cnt++;
    61         tot+=e[i].w;
    62     }
    63     }    
    64     for(int i=1;i<=m;i++) if(!e[i].flag) e[i].w-=x;
    65     if(cnt>=allow) return true;
    66     return false;
    67 }
    68 
    69 inline void work(){
    70     n=getint(); m=getint(); allow=getint();
    71     for(int i=1;i<=m;i++) {
    72     e[i].u=getint(); e[i].v=getint(); e[i].w=getint(); e[i].flag=getint();
    73     }
    74     int l=-1001,r=1001,mid;    
    75     while(l<=r) {
    76     mid=(l+r)/2;
    77     if(check(mid)) {
    78         l=mid+1; ans=tot-mid*allow;
    79     }else{
    80         r=mid-1;
    81     }
    82     }
    83     printf(OT,ans);
    84 }
    85 
    86 int main()
    87 {
    88   work();
    89   return 0;
    90 }
  • 相关阅读:
    ElasticSearch 查询语法
    自定义的带tab的可左右滑动的viewpager之二viewpager与fragment不兼容
    QT5 串口收发实例代码
    Communications link failure报错的处理
    mac 环境下mysql 不能删除schema问题的解决办法
    [置顶] How to dump redo log entry?
    pjsip视频通信开发(上层应用)之拨号界面整体界面功能实现
    windows command ftp 中文文件名乱码解决方法
    (字符串的模式匹配4.7.18)POJ 2406 Power Strings(求一个字符串的最小重复串)
    通过程序 VB.Net 或 C# 读取文本文件行数
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5674738.html
Copyright © 2020-2023  润新知