• 洛谷 P2619 【[国家集训队2]Tree I】


    参考了这篇题解,真的写的很好。

    我们直接跑最小生成树时,会出现三种情况:

    • 白边多了
    • 白边少了
    • 白边刚刚好

    对于最后一种情况,很好办,但是其他两种怎么办呢?

    我们回顾(kruskal)的算法思想,他的核心就是贪心,每次选最小的边加入,那么我们是否可以改变一下白边的优先级,让他每次加入的白边数恰好为(need)呢?可以的。我们给白边加上一个值,让他变大,再进行排序,就可以实现控制加入白边的数量了,最后减去即可。

    问题又来了,该加多少呢?枚举(-100)(100)?这样做显然花费太多时间了。考虑单调性,当我们加的数越多,选入的白边就越少,而加的越少,选入的白边越多,这样我们就可以二分了,枚举加的数,跑二分,最后输出。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    struct node{
    	int col , w , s , t;
    };
    int n , m , need , tot , p , ans , now;
    int fa[50010] , vis[200010];
    node e[200010];
    bool cmp(node x , node y){	//排序函数 先边权,后颜色 
    	if(x.w == y.w) return x.col < y.col;
    	return x.w < y.w;
    }
    int find(int x){
    	if(fa[x] == x) return x;
    	return fa[x] = find(fa[x]);
    }
    void k(){	//最小生成树 
    	sort(e + 1 , e + m + 1 , cmp);
    	for(int i = 1; i <= m; i++){
    		if(now == n - 1) break;
    		int fx = find(e[i].s) , fy = find(e[i].t);
    		if(fx == fy) continue;
    		fa[fx] = fy;
    		tot += e[i].w;
    		now++;
    		if(!e[i].col) p++;	//记录白边条数 
    	}
    }
    int main(){
    	cin >> n >> m >> need;
    	for(int i = 1; i <= m; i++){
    		int x , y , z , c;
    		cin >> x >> y >> z >> c;
    		x++ , y++;	//0开始输入 
    		e[i].s = x , e[i].t = y , e[i].w = z , e[i].col = c;
    	}
    	int l = -100 , r = 100;
    	while(l <= r){	//二分 
    		int mid = (l + r) / 2;
    		for(int i = 1; i <= m; i++)
    			if(!e[i].col) e[i].w += mid;	//每一个都加上 
    		for(int i = 1; i <= n; i++) fa[i] = i;	//初始化 
    		tot = 0 , p = 0 , now = 0;
    		k();
    		if(p >= need){	//看是否加入了合适的白边 
    			l = mid + 1;
    			ans = tot - need * mid;	//更新答案 
    		}else r = mid - 1;
    		for(int i = 1; i <= m; i++)
    			if(!e[i].col) e[i].w -= mid;	//减去 
    	}
    	cout << ans;
    	return 0;
    }
    
  • 相关阅读:
    游黄龙溪有感
    一个人的元宵节
    这个女人创业 实在让人佩服
    职场中人需要改变的9种想法
    元宵之思
    美资,台资,国有企业比较 经典!
    青年人创业最关注创业能力
    footer
    Running Scripts
    sql attention
  • 原文地址:https://www.cnblogs.com/bzzs/p/13360402.html
Copyright © 2020-2023  润新知