zoukankan      html  css  js  c++  java
  • [国家集训队2]Tree I

    题意

    Here

    思考

    (WQS) 二分,第一次做,感觉细节有点多。

    由于要求选 (need) 条白边,我们考虑每次给所有白边加上一个权值,再与黑边一起做生成树,这样就可以限制我们加入白边的个数了,但是这样我们还存在一个问题,如果有白边等于黑边权值,我们可能会先统计黑边,造成白边达不到 (need) 条的情况,我们只用在排序时加上第二关键字,优先选择白边即可。

    代码

    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return x * f;
    }
    const int M = 100010;
    const int N = 50050;
    struct node{
    	int from, to, dis, op, now;
    }edge[M << 1];
    bool cmp(node a, node b){
    	return (a.now == b.now) ? a.op < b.op : a.now < b.now;
    }
    int fa[N];
    int n, m, need, ans, sum, js;
    int findx(int x){
    	if(fa[x] == x) return x;
    	return fa[x] = findx(fa[x]);
    }
    void mergex(int x, int y){
    	int fx = findx(x), fy = findx(y);
    	if(fx == fy) return;
    	fa[fx] = fy;
    }
    bool check(int del){
    	js = 0; sum = 0;
    	for(int i=1; i<=n; i++) fa[i] = i;
    	for(int i=1; i<=m; i++){
            edge[i].now = edge[i].dis;
            if(edge[i].op == 0) edge[i].now += del;
    	}
    	sort(edge+1, edge+m+1, cmp);
    	for(int i=1; i<=m; i++){
    		int u = edge[i].from, v = edge[i].to;
    		int fu = findx(u), fv = findx(v);
    		if(fu != fv){
                mergex(u, v); sum += edge[i].dis;
                if(edge[i].op == 0) js ++;
    		}
    	}
    	return js >= need;
    }
    int main(){
    	n = read(), m = read(), need = read();
    	for(int i=1; i<=m; i++){
    		edge[i].from = read(), edge[i].to = read(), edge[i].dis = read(), edge[i].op = read();
    		edge[i].from ++, edge[i].to ++;
    		if(edge[i].op == 1) edge[i].now = edge[i].dis;
    	}
    	int l = -100, r = 100;
    	while(l <= r){
    		int mid = (l + r) >> 1;
    		if(check(mid)){
    			l = mid + 1;
    			ans = sum;
    		}
    		else r = mid - 1;
    	}
    	cout<<ans;
    	return 0;
    }
    
    

    总结

    注意二分的判断条件是大于等于 (need) ,以及排序时注意第二关键字以避免无法出解。

  • 相关阅读:
    combobox下拉框只能选择不能编辑
    nginx 虚拟主机
    nginx加密网站
    nginx平滑升级
    http网站加密
    CentOS下网卡启动、配置等ifcfg-eth0教程
    CentOS5.6系统中安装并使用USB无线网卡(配置成功) 转
    【RedHat/Centos】利用iso镜像做本地yum源 转
    centOS6.0 64 位将光盘作为yum源(转)
    Linux安装无线网卡驱动,实现Linux无线上网 转
  • 原文地址:https://www.cnblogs.com/alecli/p/9908721.html
Copyright © 2011-2022 走看看