[BZOJ 2654] tree

[题目链接]

         https://www.lydsy.com/JudgeOnline/problem.php?id=2654

[算法]

        给白色边都加上一个值,会使得最小生成树上的白边数量减少,不妨二分给白色边加上的值 ,  检验答案时用Kruskal求最小生成树即可

        时间复杂度 : O(NlogN)

[代码]

       

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
#define MAXM 200010

struct edge
{
    int u , v , w , type;
} e[MAXN];

int tot , n , m , value , ans;
int fa[MAXN];

template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
template <typename T> inline void read(T &x)
{
   T f = 1; x = 0;
   char c = getchar();
   for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
   for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
   x *= f;
}
inline int get_root(int x)
{
    if (fa[x] == x) return x;
    return fa[x] = get_root(fa[x]);
}
inline bool cmp(edge a , edge b)
{
    return a.w == b.w ? a.type < b.type : a.w < b.w;
}
inline bool check(int mid)
{
    int cnt = 0; 
    tot = 0;
    for (int i = 1; i <= n; i++) 
        fa[i] = i;
    for (int i = 1; i <= m; i++)
        if (!e[i].type) e[i].w += mid;    
    sort(e + 1 , e + m + 1 , cmp);
    for (int i = 1; i <= m; i++)
    {
        int su = get_root(e[i].u) , sv = get_root(e[i].v);
        if (su != sv)
        {
            fa[su] = sv;
            tot += e[i].w;
            if (!e[i].type) ++cnt;
        }
    }
    for (int i = 1; i <= m; i++) 
        if (!e[i].type) e[i].w -= mid;
    return cnt >= value;
}

int main()
{
    
    read(n); read(m); read(value);
    for (int i = 1; i <= m; i++)
    {
        read(e[i].u);
        read(e[i].v);
        read(e[i].w);
        ++e[i].u; ++e[i].v;
        read(e[i].type);    
    }
    int l = -105 , r = 105 , ans = 0;
    while (l <= r)
    {
        int mid = (l + r) / 2;
        if (check(mid))
        {
            ans = tot - value * mid;
            l = mid + 1;    
        } else r = mid - 1;
    }
    printf("%d\n" , ans);
    
    return 0;
}

 

posted @ 2018-10-30 18:50  evenbao  阅读(160)  评论(0编辑  收藏  举报