• BZOJ2654:Tree


    题面:https://www.lydsy.com/JudgeOnline/problem.php?id=2654
    题解:
    我们考虑求最小生成树算法kruskal的这个过程。
    建立一个平面直角坐标系,(x)轴意义为选了多少条边,(y)轴是代价。
    可以发现,因为kruskal算法先将所有边排序,所以随着(x)的增大,
    (y)的增大幅度也更大了。形式化的讲,就是这个折线的斜率是单调不降的。
    由此,可以考虑wqs二分。我们每次给所有白边加一个权值(mid),然后做
    最小生成树。显然,(mid)越大,MST里的白边数量是不增的。
    最后的答案就是(sum)(v[i]-need*mid),(edge_i) (in) MST。
    注意:可能会出现无法找到刚好(need)个白边的情况。
    我们只需在每次白边个数大于等于(need)的时候更新答案就行了。
    因为出现这种情况肯定是因为在边界处有很多权值相同的边。
    当然,把颜色作为第二关键字排序也是可行的一个办法。
    时间复杂度:(O(mlogmloga[i]))
    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define re register int
    #define F(x,y,z) for(re x=y;x<=z;x++)
    #define FOR(x,y,z) for(re x=y;x>=z;x--)
    typedef long long ll;
    #define I inline void
    #define IN inline int
    #define C(x,y) memset(x,y,sizeof(x))
    #define STS system("pause")
    template<class D>I read(D &res){
    	res=0;register D g=1;register char ch=getchar();
    	while(!isdigit(ch)){
    		if(ch=='-')g=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch)){
    		res=(res<<3)+(res<<1)+(ch^48);
    		ch=getchar();
    	}
    	res*=g;
    }
    struct E{
    	int a,b,v,c;
    	friend bool operator < (E x,E y){
    		return x.v==y.v?x.c<y.c:x.v<y.v;
    	}
    }e[101000];
    int n,m,K,ans,num,cnt,sum,fa[101000];
    IN find(int x){
    	return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    IN join(int x,int y){
    	x=find(x);y=find(y);
    	if(x==y)return 0;
    	fa[x]=y;return 1;
    }
    I ck(int w){
    	F(i,1,m)if(!e[i].c)e[i].v+=w;
    	sort(e+1,e+1+m);
    	F(i,1,n)fa[i]=i;
    	num=cnt=sum=0;
    	F(i,1,m){
    		if(sum<n-1&&join(e[i].a,e[i].b))num+=e[i].v,sum++,cnt+=(e[i].c^1);
    		if(!e[i].c)e[i].v-=w;
    	}
    }
    I divided(int x,int y){
    	if(x>=y)return;
    	re mid=(x+y)>>1;
    	ck(mid);
    	if(cnt>=K)ans=num-K*mid,x=mid+1;
    	else y=mid-1;
    	divided(x,y);
    }
    int main(){
    	read(n);read(m);read(K);
    	F(i,1,m){
    		read(e[i].a);read(e[i].b);read(e[i].v);read(e[i].c);e[i].a++;e[i].b++;
    	}
    	sort(e+1,e+1+m);
    	divided(-105,105);
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    linux加载和卸载模块
    java 面试题之银行业务系统
    java 面试题之交通灯管理系统
    java 实现类似spring的可配置的AOP框架
    分析JVM动态生成的类
    最长上升子序列(模板)
    项目管理模式
    让thinkphp 支持ftp上传到远程,ftp删除
    hdu 1280 前m大的数 哈希
    互联网+脑科学,中国脑计划的机会
  • 原文地址:https://www.cnblogs.com/Purple-wzy/p/12186580.html
Copyright © 2020-2023  润新知