luogu P5633 最小度限制生成树 wqs二分
LINK:最小度限制生成树
还是WQS二分的模板题 不过相当于我WQS二分的复习题.
对于求出强制k个的答案 dp能做不过复杂度太高了。
世界上定义F(x)表示选出x个的答案 画成图像 其实形成了一个凸包。
利用斜率就可以去切这个凸包了。
二分这个斜率 不断的在凸包上切 知道值刚好等于题目中要求的k 有的时候可能会出现mid时为k-1 mid+1时是k的情况 此时可以优先白边选使得在mid时满足要求。
可能此时x>k的 不过可以证明可以构造出来k条边的情况 然后减掉这k条边的权值即可。
卡了下常 跑的挺快的。
code
//#include<bits\stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 100000000
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define gc(a) scanf("%s",a+1)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define P 1000000007
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-9
#define sq sqrt
#define mod 998244353
#define S second
#define F first
#define op(x) t[x].op
#define d(x) t[x].d
#define Set(a,v) memset(a,v,sizeof(a))
#define pf(x) ((x)*(x))
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    RE int x=0,f=1;RE char ch=getc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
    return x*f;
}
const int MAXN=500010,maxn=50010;
int n,m,s,k,cnt1,cnt2,cnt,all,ans;ll res;
int f[maxn];
struct wy
{
	int x,y,z;
	inline bool friend operator <(wy a,wy b){return a.z<b.z;}
}t[MAXN],w[maxn],tmp[MAXN];
inline int getfather(int x){return x==f[x]?x:f[x]=getfather(f[x]);}
inline bool merge(int x,int y)
{
	int xx=getfather(x);
	int yy=getfather(y);
	if(xx==yy)return 0;
	f[xx]=yy;return 1;
}
inline bool check(int x)
{
	int i=1,j=1;
	cnt=0,all=0;res=0;
	rep(1,n,i)f[i]=i;
	rep(1,m,v)
	{
		if(i<=cnt1&&j<=cnt2)
		{
			if(t[i].z-x<=w[j].z)
			{
				if(merge(t[i].x,t[i].y))++cnt,res+=t[i].z-x,++all;
				++i;
			}
			else
			{
				if(merge(w[j].x,w[j].y))res+=w[j].z,++all;
				++j;
			}
			continue;
		}
		if(i<=cnt1){if(merge(t[i].x,t[i].y))++cnt,res+=t[i].z-x,++all;++i;}
		if(j<=cnt2){if(merge(w[j].x,w[j].y))res+=w[j].z,++all;++j;}
		if(all==n-1)break;
	}
	return cnt>=k;
}
signed main()
{
	//freopen("1.in","r",stdin);
	get(n);get(m);get(s);get(k);
	rep(1,n,i)f[i]=i;
	rep(1,m,i)
	{
		int get(x),get(y),get(z);
		if(x==s||y==s)t[++cnt1]=(wy){x,y,z};
		else tmp[++cnt2]=(wy){x,y,z};
		ans+=merge(x,y);
	}
	if(cnt1<k){puts("Impossible");return 0;}
	if(ans!=n-1){puts("Impossible");return 0;}
	rep(1,n,i)f[i]=i;
	sort(t+1,t+1+cnt1);
	sort(tmp+1,tmp+1+cnt2);
	int ww=0;
	rep(1,cnt2,i)if(merge(tmp[i].x,tmp[i].y))w[++ww]=tmp[i];
	cnt2=ww;
	int l=-INF,r=INF;
	if(!check(r)){puts("Impossible");return 0;}
	if(check(l)&&cnt!=k){puts("Impossible");return 0;}
	while(l<r)
	{
		int mid=(l+r)>>1;
		if(check(mid))r=mid;
		else l=mid+1;
	}
	check(l);
	putl(res+(ll)k*l);return 0;
}
luogu P5633 最小度限制生成树 wqs二分的更多相关文章
- 决策单调性&wqs二分
		其实是一个还算 trivial 的知识点吧--早在 2019 年我就接触过了,然鹅当时由于没认真学并没有把自己学懂,故今复学之( 1. 决策单调性 引入:在求解 DP 问题的过程中我们常常遇到这样的问 ... 
- Luogu P2619 [国家集训队2]Tree I(WQS二分+最小生成树)
		P2619 [国家集训队2]Tree I 题意 题目描述 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有\(need\)条白色边的生成树. 题目保证有解. 输入输出格式 输入格式 ... 
- luogu CF125E MST Company wqs二分 构造
		LINK:CF125E MST Company 难点在于构造 前面说到了求最小值 可以二分出斜率k然后进行\(Kruskal\) 然后可以得到最小值.\(mx\)为值域. 得到最小值之后还有一个构造问 ... 
- 关于WQS二分算法以及其一个细节证明
		应用分析 它的作用就是题目给了一个选物品的限制条件,要求刚好选$m$个,让你最大化(最小化)权值, 然后其特点就是当选的物品越多的时候权值越大(越小). 算法分析 我们先不考虑物品限制条件, 假定我们 ... 
- [总结] wqs二分学习笔记
		论文 提出问题 在某些题目中,强制规定只能选 \(k\) 个物品,选多少个和怎么选都会影响收益,问最优答案. 算法思想 对于上述描述的题目,大部分都可以通过枚举选择物品的个数做到 \(O(nk^2)\ ... 
- [九省联考2018]林克卡特树(DP+wqs二分)
		对于k=0和k=1的点,可以直接求树的直径. 然后对于60分,有一个重要的转化:就是求在树中找出k+1条点不相交的链后的最大连续边权和. 这个DP就好.$O(nk^2)$ 然后我们完全不可以想到,将b ... 
- SCUT - 365 - 鹏哥的数字集合 - wqs二分 - 斜率优化dp
		https://scut.online/p/365 https://www.luogu.org/problemnew/solution/P2365 写这篇的时候还不是很明白,看一下这个东西. http ... 
- CF802O-April Fools‘ Problem(hard)【wqs二分,优先队列】
		正题 题目链接:https://www.luogu.com.cn/problem/CF802O 题目大意 \(n\)天每条有\(a_i\)和\(b_i\). 每条可以花费\(a_i\)准备至多一道题, ... 
- luoguP4383 [八省联考2018]林克卡特树(树上dp,wqs二分)
		luoguP4383 [八省联考2018]林克卡特树(树上dp,wqs二分) Luogu 题解时间 $ k $ 条边权为 $ 0 $ 的边. 是的,边权为零. 转化成选正好 $ k+1 $ 条链. $ ... 
随机推荐
- show me bug
			比较版本号 前者大返回1 后者大返回-1 两者一样大返回0 #include <iostream> #include<string> using namespace std; ... 
- List的isEmpty与==null的区别
			集合的判空一般判定方法 ArrayList<Person> list = null; System.out.println(null == list);//return true Syst ... 
- day52作业
			做一个小米商城首页的头部 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ... 
- java 基本语法(八) 数组(一) 数组的概述
			* 1.数组的理解:数组(Array),是多个相同类型数据一定顺序排列的集合,并使用一个名字命名, * 并通过编号的方式对这些数据进行统一管理. * * 2.数组相关的概念: * >数组名 * ... 
- Flask 基础组件(二):配置文件
			配置参数 flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为: { 'DEBUG': get_debug_flag(default=False), 是否开启 ... 
- 循序渐进VUE+Element 前端应用开发(17)--- 菜单资源管理
			在权限管理系统中,菜单也属于权限控制的一个资源,应该直接应用于角色,和权限功能点一样,属于角色控制的一环.不同角色用户,登录系统后,出现的系统菜单是不同的.在VUE+Element 前端中,我们菜单结 ... 
- 从零开始学Electron笔记(六)
			在之前的文章我们介绍了一下Electron如何通过链接打开浏览器和嵌入网页,接下来我们继续说一下Electron中的对话框 Dialog和消息通知 Notification. 在之前的文章中其实我们是 ... 
- 数据结构C语言实现----出栈操作
			代码如下: #include<stdio.h> #include<stdlib.h> typedef struct { char *base; char *top; int s ... 
- Python Ethical Hacking - Persistence(2)
			Polish the Python code by adding the become_persistent function. #!/usr/bin/env python import json i ... 
- html-webpack-plugin在html中插入数据
			html-webpack-plugin在html中插入数据 <!DOCTYPE html> <html> <head> <meta charset=" ... 
