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

    给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有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


      显然是MST,但是在Kruskal的过程中我们无法控制白边的数量。如果考虑修改边值,可以发现如果给白边的边权都加上一个delta,那么白边的数量随着delta的增大而减小。所以可以二分它去控制白边的数量。

    Code

      1 /**
      2  * bzoj
      3  * Problem#2654
      4  * Accepted
      5  * Time:1892ms
      6  * Memory:3052k
      7  */
      8 #include<iostream>
      9 #include<cstdio>
     10 #include<ctime>
     11 #include<cctype>
     12 #include<cstring>
     13 #include<cstdlib>
     14 #include<fstream>
     15 #include<sstream>
     16 #include<algorithm>
     17 #include<map>
     18 #include<set>
     19 #include<stack>
     20 #include<queue>
     21 #include<vector>
     22 #include<stack>
     23 #ifndef WIN32
     24 #define Auto "%lld"
     25 #else
     26 #define Auto "%I64d"
     27 #endif
     28 using namespace std;
     29 typedef bool boolean;
     30 const signed int inf = (signed)((1u << 31) - 1);
     31 #define smin(a, b) a = min(a, b)
     32 #define smax(a, b) a = max(a, b)
     33 #define max3(a, b, c) max(a, max(b, c))
     34 #define min3(a, b, c) min(a, min(b, c))
     35 template<typename T>
     36 inline boolean readInteger(T& u){
     37     char x;
     38     int aFlag = 1;
     39     while(!isdigit((x = getchar())) && x != '-' && x != -1);
     40     if(x == -1) {
     41         ungetc(x, stdin);
     42         return false;
     43     }
     44     if(x == '-'){
     45         x = getchar();
     46         aFlag = -1;
     47     }
     48     for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0');
     49     ungetc(x, stdin);
     50     u *= aFlag;
     51     return true;
     52 }
     53 
     54 typedef class union_found{
     55     public:
     56         int *f;
     57         union_found():f(NULL) {}
     58         union_found(int points) {
     59             f = new int[(const int)(points + 1)];
     60             clear(points);
     61         }
     62         int find(int x) {
     63             if(f[x] != x)    return f[x] = find(f[x]);
     64             return f[x];
     65         }
     66         void unit(int fa, int so) {
     67             int ffa = find(fa);
     68             int fso = find(so);
     69             f[fso] = ffa;
     70         }
     71         boolean connected(int a, int b) {
     72             return find(a) == find(b);
     73         }
     74         void clear(int points) {
     75             for(int i = 0; i <= points; i++)
     76                 f[i] = i;
     77         }
     78 }union_found;
     79 
     80 int delta = 0;
     81 
     82 typedef class Edge {
     83     public:
     84         int from;
     85         int end;
     86         int val;
     87         boolean col;
     88         
     89         inline int getVal() const {
     90             if(col)    return val + delta;
     91             return val;
     92         }
     93 }Edge;
     94 
     95 boolean operator < (const Edge& a, const Edge& b) {
     96     return a.getVal() < b.getVal();
     97 }
     98 
     99 int n, m, lim;
    100 union_found uf;
    101 Edge* edge;
    102 
    103 inline void init() {
    104     readInteger(n);
    105     readInteger(m);
    106     readInteger(lim);
    107     uf = union_found(n);
    108     edge = new Edge[(const int)(m + 1)];
    109     for(int i = 0; i < m; i++) {
    110         readInteger(edge[i].from);
    111         readInteger(edge[i].end);
    112         readInteger(edge[i].val);
    113         readInteger(edge[i].col);
    114         edge[i].col ^= 1;
    115     }
    116 }
    117 
    118 int res = 0;
    119 int kruskal(int mid) {
    120     delta = mid;
    121     res = 0;
    122     uf.clear(n);
    123     sort(edge, edge + m);
    124     int fw = 0, fin = 0;
    125     for(int i = 0; i < m; i++) {
    126         if(!uf.connected(edge[i].from, edge[i].end)) {
    127             uf.unit(edge[i].from, edge[i].end);
    128             fw += edge[i].col, fin ++, res += edge[i].val;
    129         }
    130     }
    131     return fw;
    132 }
    133 
    134 
    135 inline void solve() {
    136     int l = -100, r = 100, c;
    137     while(l <= r) {
    138         int mid = (l + r) >> 1;
    139         if((c = kruskal(mid)) < lim)    r = mid - 1;
    140         else if(c > lim)    l = mid + 1;
    141         else break;
    142     }
    143     printf("%d
    ", res);
    144 }
    145 
    146 int main() {
    147     init();
    148     solve();
    149     return 0;
    150 }
  • 相关阅读:
    Ubuntu adb device
    ubuntu系统下创建软件桌面快捷方式
    Ubuntu 配置java环境变量
    Ubuntu 12.04 安装Chrome步骤
    java和php中static+final+synchronized 总结
    Sensor Hub 初探
    Ionic+PhoneGap+ Cordova
    Ionic初探 + 混合app的尝试
    ubuntu+dpkg+apt-get+aptitude 区别
    ubuntu下桌面系统及切换gdm+kdm+lightdm
  • 原文地址:https://www.cnblogs.com/yyf0309/p/7125479.html
Copyright © 2011-2022 走看看