P5633 最小度限制生成树

题目

分析

\(wqs\)二分经典题。

原函数显然是一个上凸包,于是考虑\(wqs\)二分。

可以考虑把边集分成两类,一类是和\(s\)直接相连的,一类是和\(s\)不连接的。

然后显然我们每一次只会改变前者的值,这样我们可以只在最开始的地方给两类边分别排好序,然后每次归并即可。

接下来就是一般最小生成树的过程了。

这样时间复杂度是\(O(n\log n)\)的。

代码

#include<bits/stdc++.h>
using namespace std;
//#define getchar()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
//char buf[1<<21],*p1=buf,*p2=buf;
template <typename T>
inline void read(T &x){
	x=0;char ch=getchar();bool f=false;
	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	x=f?-x:x;
	return ;
}
template <typename T>
inline void write(T x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10^48);
	return ;
}
#define ll long long
const int N=5e5+5;
const ll INF=1e9;
int n,m,k,s;
struct Edge{
	int u,v;ll w;
	inline bool operator < (const Edge &B)const{return w<B.w;}
	Edge(int u=0,int v=0,ll w=0):u(u),v(v),w(w){}
}E1[N],E2[N],E[N];
int fa[N],top1,top2;
int Getfa(int x){return fa[x]==x?x:fa[x]=Getfa(fa[x]);}
ll sum,tot,cnt;
bool Kruskal(ll mid){
	tot=sum=m=cnt=0;
	for(int i=1;i<=n;i++) fa[i]=i;
	for(int i=1;i<=top1;i++) E1[i].w+=mid;
	int j=1;
	for(int i=1;i<=top2;i++){
		while(j<=top1&&E1[j].w<=E2[i].w) E[++m]=E1[j],j++;
		E[++m]=E2[i];
	}
	while(j<=top1) E[++m]=E1[j++];
	for(int i=1;i<=m;i++){
		int u=Getfa(E[i].u),v=Getfa(E[i].v);
		if(u==v) continue;
		fa[u]=v;sum+=E[i].w;
		if(E[i].u==s||E[i].v==s) tot++;
		if(cnt==n-1) return tot>=k;
	}
	for(int i=1;i<=top1;i++) E1[i].w-=mid;
	return tot>=k;
}
signed main(){
	read(n),read(m);read(s),read(k);
	for(int i=1,u,v,w;i<=m;i++){
		read(u),read(v),read(w);
		if(u==s||v==s) E1[++top1]=Edge(u,v,w);
		else E2[++top2]=Edge(u,v,w);
	}
	sort(E1+1,E1+top1+1),sort(E2+1,E2+top2+1);
	ll l=-INF,r=INF,ans=-1;
	if(!Kruskal(l)){puts("Impossible");return 0;}
	if(Kruskal(r)&&tot>k){puts("Impossible");return 0;}
	while(l<r){
		ll mid=l+r+1>>1;
		if(Kruskal(mid)) l=mid;
		else r=mid-1;
	}
	Kruskal(r);
	write(sum-k*r);
	return 0;
}

感受

这个分两类边排序然后归并的技巧很巧妙,直接省下了1个\(\log\),可以记下。

posted @ 2021-07-21 21:34  __Anchor  阅读(271)  评论(0)    收藏  举报