zoukankan      html  css  js  c++  java
  • BZOJ 2654: tree( 二分 + MST )

    我们给白色的边增加权值 , 则选到的白色边就会变多 , 因此可以二分一下.

    不过这道题有点小坑... 

    -------------------------------------------------------------------------------------------

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
     
    #define rep( i , n ) for( int i = 0 ; i < n ; ++i )
    #define clr( x , c ) memset( x , c , sizeof( x ) )
      
    using namespace std;
     
    const int maxn = 50000 + 5;
    const int maxm = 100000 + 5;
     
    int add , n , m , need;
    int p[ maxn ];
     
    int find( int x ) {
    return p[ x ] == x ? x : p[ x ] = find( p[ x ] );
    }
     
    void UF_clear() {
    rep( i , n ) p[ i ] = i;
     
    struct edge {
    int u , v , d , s;
    void Read() {
    scanf( "%d%d%d%d" , &u , &v , &d , &s );
    s ^= 1;
    }
    bool operator < ( const edge &e ) const {
    return d < e.d || ( d == e.d && s > e.s );
    }
    };
     
    edge E[ maxm ];
     
    struct node {
    int L , R , w;
    };
     
    int kruskal() {
    int ans = 0 , cnt = 0;
    UF_clear();
    rep( i , m ) {
    edge &e = E[ i ];
    if( e.s ) e.d += add;
    }
    sort( E , E + m );
    rep( i , m ) {
    edge &e = E[ i ];
    int a = find( e.u ) , b = find( e.v );
    if( a != b ) {
    p[ a ] = b;
    ans += e.d;
    if( e.s ) cnt++;
    }
    }
    rep( i , m ) {
    edge &e = E[ i ];
    if( e.s ) e.d -= add;
    }
    return cnt >= need ? ans : -1;
    }
     
    int main() {
    freopen( "test.in" , "r" , stdin );
    cin >> n >> m >> need;
    rep( i , m )
       E[ i ].Read();
    int ans;
    int L = -300 , R = 300;
    while( L <= R ) {
    add = ( L + R ) >> 1;
    int x = kruskal();
    if( x != -1 ) {
    ans = x - need * add;
    L = add + 1;
    } else 
       R = add - 1;
    }
    cout << ans << " ";
    return 0;
    }

    ------------------------------------------------------------------------------------------- 

    2654: tree

    Time Limit: 30 Sec  Memory Limit: 512 MB
    Submit: 578  Solved: 214
    [Submit][Status][Discuss]

    Description

      给你一个无向带权连通图,每条边是黑色或白色。让你求一棵最小权的恰好有need条白色边的生成树。
      题目保证有解。

    Input

      第一行V,E,need分别表示点数,边数和需要的白色边数。
      接下来E行
      每行s,t,c,col表示这边的端点(点从0开始标号),边权,颜色(0白色1黑色)。

    Output

      一行表示所求生成树的边权和。

    Sample Input

    2 2 1
    0 1 1 1
    0 1 2 0


    Sample Output

    2

    HINT

    数据规模和约定

      0:V<=10

      1,2,3:V<=15

      0,..,19:V<=50000,E<=100000

      所有数据边权为[1,100]中的正整数。

    Source

  • 相关阅读:
    计算机操作系统之进程管理
    剑指offer——两个链表的第一个公共结点
    剑指offer——数字在排序数组中出现的次数
    剑指offer——二叉树的深度与平衡二叉树的判断
    剑指offer——数组中只出现一次的数字
    剑指offer——和为s的两个数字VS和为s的连续正数序列
    剑指offer——翻转单词顺序VS左旋转字符串
    剑指offer——扑克牌的顺子
    剑指offer——圆圈中最后剩下的数字
    剑指offer——求1+2+...+n
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4573693.html
Copyright © 2011-2022 走看看