P2619 [国家集训队]Tree I(wqs二分)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2619 [国家集训队]Tree I(wqs二分)相关的知识,希望对你有一定的参考价值。

P2619 [国家集训队]Tree I(wqs二分)

wqs是一个大佬,wqs二分是基于 凸包型的问题,斜率的二分。

本题设 ( x , g ( x ) ) (x,g(x)) (x,g(x)) 表示恰好选择 x x x条白边,对应最小MST的权值和 g ( x ) g(x) g(x)

可以用平方的dp 证明该函数形状是个下凸的。

然后就可以上wqs二分了。

我们二分增量,也就是直线的斜率,在本题就是所有白边权值的增量。

然后用Kruskal找到最优值 a n s ans ans,显然我们可以同时求出对应的白边的数量 x ′ x' x

如果 x ′ ≥ n e e d x'\\ge need xneed ,则说明二分的斜率 m i d mid mid 偏小, l = m i d + 1 l=mid+1 l=mid+1,然后更新 r e s = a n s − m i d × n e e d res =ans-mid\\times need res=ansmid×need。这里是还原mid对应的影响。

最后的 r e s res res就是答案了。

时间复杂度: O ( m l o g m × l o g W ) O(mlogm\\times logW) O(mlogm×logW)

// Problem: P2619 [国家集训队]Tree I
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2619
// Memory Limit: 500 MB
// Time Limit: 2000 ms
// Date: 2022-04-11 21:33:52
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=5e4+5,M=1e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const int hashmod[4] = 402653189,805306457,1610612741,998244353;
#define mst(a,b) memset(a,b,sizeof a)
#define db double
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define ios ios::sync_with_stdio(false),cin.tie(nullptr) 
void Print(int *a,int n)
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 

template <typename T>		//x=max(x,y)  x=min(x,y)
void cmx(T &x,T y)
	if(x<y) x=y;

template <typename T>
void cmn(T &x,T y)
	if(x>y) x=y;

struct Kruskal
#define il inline	
	struct edge
		int u,v,w,o;
		bool operator<(const edge &e)const
			return w==e.w?o<e.o:w<e.w;
		
	e[M];
	int s[N];
	il int find(int x)
		return s[x]==x?x:s[x]=find(s[x]);
	
	int n,m,need;
	il void init()
		scanf("%d%d%d",&n,&m,&need);
		rep(i,1,m)
			int u,v,w,o;
			scanf("%d%d%d%d",&u,&v,&w,&o);
			u++,v++;
			e[i] = u,v,w,o;
		
		int l = -100,r = 100;
		ll res  = 0,ans = 0;
		int cnt = 0;
		//printf("n=%d m=%d\\n",n,m);
		while(l<=r)
			int mid = l+r>>1;
			rep(i,1,m)
				if(!e[i].o) e[i].w+=mid;
			
			solve(cnt,ans);
			//printf("cnt=%d\\n",cnt);
			if(cnt>=need) res = ans-need*mid, l = mid+1;
			else r = mid-1;
			rep(i,1,m)
				if(!e[i].o) e[i].w-=mid;
			
		
		printf("%lld\\n",res);
	
	il void solve(int &cnt,ll &ans)
		sort(e+1,e+m+1);
		rep(i,1,n) s[i] = i;
		cnt = 0;
		ans = 0;
		int cc = 0;
		rep(i,1,m)
			int u = e[i].u, v = e[i].v, w = e[i].w;
			u=find(u),v=find(v);
			if(u!=v)
				ans += w;
				s[u] = v;
				cc++;
				if(!e[i].o) cnt++;
			
			if(cc == n - 1) 
				return;
			
		
	
T;
int main()
	T.init();
	return 0;



关于WQS二分可以参考下面的文章。

传送门

题解区

以上是关于P2619 [国家集训队]Tree I(wqs二分)的主要内容,如果未能解决你的问题,请参考以下文章

P2619 [国家集训队2]Tree I

BZOJ2654 tree (wqs二分)

[国家集训队2]Tree I

[算法相关]wqs 二分

CF739E Gosha is hunting(wqs二分套wqs二分)

CF739EGosha is hunting(WQS二分套WQS二分)