• 【bzoj2654】tree 二分+Kruscal


    题目描述

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

    输入

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

    输出

    一行表示所求生成树的边权和。
    V<=50000,E<=100000,所有数据边权为[1,100]中的正整数。

    样例输入

    2 2 1
    0 1 1 1
    0 1 2 0

    样例输出

    2


    题解

    二分+Kruscal

    这也算是一道神题了吧...

    可以发现,如果白色边的权值全部加上一个值,选择是不会变化的。并且当最小生成树恰好满足题目要求时一定是最优解。

    因此我们可以二分白色边加上的权值,求最小生成树,直到得出满足条件的白色边个数为止。最后我们根据选择的方案计算答案即可。

    如果先对于所有边排序的话,时间复杂度为 $O(mlog m)$。

    #include <cstdio>
    #include <algorithm>
    #define N 50010
    using namespace std;
    struct data
    {
    	int x , y , z;
    	data(int a = 0 , int b = 0 , int c = 0) {x = a , y = b , z = c;}
    	bool operator<(const data &a)const {return z < a.z;}
    }b[N << 1] , w[N << 1];
    int tb , tw , n , f[N] , sum;
    int find(int x)
    {
    	return x == f[x] ? x : f[x] = find(f[x]);
    }
    int solve(int mid)
    {
    	int i , pb = 1 , pw = 1 , ans = 0;
    	sum = 0;
    	for(i = 0 ; i < n ; i ++ ) f[i] = i;
    	while(pb <= tb || pw <= tw)
    	{
    		if(pw > tw || (pb <= tb && b[pb].z < w[pw].z + mid))
    		{
    			if(find(b[pb].x) != find(b[pb].y)) sum += b[pb].z , f[f[b[pb].x]] = f[b[pb].y];
    			pb ++ ;
    		}
    		else
    		{
    			if(find(w[pw].x) != find(w[pw].y)) sum += w[pw].z , f[f[w[pw].x]] = f[w[pw].y] , ans ++ ;
    			pw ++ ;
    		}
    	}
    	return ans;
    }
    int main()
    {
    	int m , k , i , x , y , z , p , l = -100 , r = 100 , mid , ans;
    	scanf("%d%d%d" , &n , &m , &k);
    	for(i = 1 ; i <= m ; i ++ )
    	{
    		scanf("%d%d%d%d" , &x , &y , &z , &p);
    		if(p) b[++tb] = data(x , y , z);
    		else w[++tw] = data(x , y , z);
    	}
    	sort(b + 1 , b + tb + 1) , sort(w + 1 , w + tw + 1);
    	while(l <= r)
    	{
    		mid = (l + r) >> 1;
    		if(solve(mid) >= k) ans = mid , l = mid + 1;
    		else r = mid - 1;
    	}
    	solve(ans);
    	printf("%d
    " , sum);
    	return 0;
    }
    

     

  • 相关阅读:
    转_前端开发技术概要
    获取链接的参数
    tabIndex 主要是美化tab键切换的体现
    textarea自动增高并隐藏滚动条
    Zen Coding:css,html缩写替换大观让你的html,css飞起来
    动态添加链接颜色代码
    转javascript 数组
    为指定元素增加样式
    1 CodeBox代码盒子 alpha版发布
    转发布js支持Firefox的加入收藏代码
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7843254.html
Copyright © 2020-2023  润新知