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二分的更多相关文章

  1. 决策单调性&wqs二分

    其实是一个还算 trivial 的知识点吧--早在 2019 年我就接触过了,然鹅当时由于没认真学并没有把自己学懂,故今复学之( 1. 决策单调性 引入:在求解 DP 问题的过程中我们常常遇到这样的问 ...

  2. Luogu P2619 [国家集训队2]Tree I(WQS二分+最小生成树)

    P2619 [国家集训队2]Tree I 题意 题目描述 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有\(need\)条白色边的生成树. 题目保证有解. 输入输出格式 输入格式 ...

  3. luogu CF125E MST Company wqs二分 构造

    LINK:CF125E MST Company 难点在于构造 前面说到了求最小值 可以二分出斜率k然后进行\(Kruskal\) 然后可以得到最小值.\(mx\)为值域. 得到最小值之后还有一个构造问 ...

  4. 关于WQS二分算法以及其一个细节证明

    应用分析 它的作用就是题目给了一个选物品的限制条件,要求刚好选$m$个,让你最大化(最小化)权值, 然后其特点就是当选的物品越多的时候权值越大(越小). 算法分析 我们先不考虑物品限制条件, 假定我们 ...

  5. [总结] wqs二分学习笔记

    论文 提出问题 在某些题目中,强制规定只能选 \(k\) 个物品,选多少个和怎么选都会影响收益,问最优答案. 算法思想 对于上述描述的题目,大部分都可以通过枚举选择物品的个数做到 \(O(nk^2)\ ...

  6. [九省联考2018]林克卡特树(DP+wqs二分)

    对于k=0和k=1的点,可以直接求树的直径. 然后对于60分,有一个重要的转化:就是求在树中找出k+1条点不相交的链后的最大连续边权和. 这个DP就好.$O(nk^2)$ 然后我们完全不可以想到,将b ...

  7. SCUT - 365 - 鹏哥的数字集合 - wqs二分 - 斜率优化dp

    https://scut.online/p/365 https://www.luogu.org/problemnew/solution/P2365 写这篇的时候还不是很明白,看一下这个东西. http ...

  8. CF802O-April Fools‘ Problem(hard)【wqs二分,优先队列】

    正题 题目链接:https://www.luogu.com.cn/problem/CF802O 题目大意 \(n\)天每条有\(a_i\)和\(b_i\). 每条可以花费\(a_i\)准备至多一道题, ...

  9. luoguP4383 [八省联考2018]林克卡特树(树上dp,wqs二分)

    luoguP4383 [八省联考2018]林克卡特树(树上dp,wqs二分) Luogu 题解时间 $ k $ 条边权为 $ 0 $ 的边. 是的,边权为零. 转化成选正好 $ k+1 $ 条链. $ ...

随机推荐

  1. HTML5 Canvas绘图基本使用方法, H5使用Canvas绘图

    Canvas 是H5的一部分,允许脚本语言动态渲染图像.Canvas 定义一个区域,可以由html属性定义该区域的宽高,javascript代码可以访问该区域,通过一整套完整的绘图功能(API),在网 ...

  2. 什么是DevOps?该如何正确的在企业内进行实践

    传统IT技术团队中通常都有多个独立的组织-开发团队.测试团队和运维团队.开发团队进行软件开发.测试团队进行软件测试,运维团队致力于部署,负载平衡和发布管理. 他们之间的职能有时重叠.有时依赖.有时候会 ...

  3. Python 最强 IDE 详细使用指南!

    PyCharm 是一种 Python IDE,可以帮助程序员节约时间,提高生产效率.那么具体如何使用呢?本文从 PyCharm 安装到插件.外部工具.专业版功能等进行了一一介绍,希望能够帮助到大家.作 ...

  4. CentOS7下安装Docker《超详细新手教程》

    1.使用 root 权限登录 Centos.确保 yum 包更新到最新. sudo yum update 2.卸载旧版本(如果安装过旧版本的话) sudo yum remove docker dock ...

  5. STL测试3)优先级队列实现二叉堆

    用法: big_heap.empty();判断堆是否为空 big_heap.pop();弹出栈顶元素最大值 big_heap.push(x);将x添加到最大堆 big_heap.top();返回栈顶元 ...

  6. MySQL 对window函数执行sum函数疑似Bug

    MySQL 对window函数执行sum函数疑似Bug 使用MySql的窗口函数统计数据时,发现一个小的问题,与大家一起探讨下. 环境配置: mysql-installer-community-8.0 ...

  7. redis(十六):Redis 安装,部署(LINUX环境下)

    第一步:下载安装包 访问https://redis.io/download  到官网进行下载.这里下载最新的4.0版本. 第二步:安装 1.通过远程管理工具,将压缩包拷贝到Linux服务器中,执行解压 ...

  8. Django框架06 /orm多表操作

    Django框架06 /orm多表操作 目录 Django框架06 /orm多表操作 1. admin相关操作 2. 创建模型 3. 增加 4. 删除 5. 修改 6. 基于对象的跨表查询 7. 基于 ...

  9. JVM垃圾回收(五)

    低延迟垃圾收集器 衡量垃圾收集器的三项最重要的指标是: 内存占用(Footprint).吞吐量(Throughput)和延迟(Latency).三者总体的表现会随技术进步而越来越好,但是要在这三个方面 ...

  10. 句柄Handle的释放(8)

    本篇首先介绍几个与句柄分配与释放密切相关的类,然后重点介绍句柄的释放. 1.HandleArea.Area与Chunk 句柄都是在HandleArea中分配并存储的,类的定义如下: // Thread ...