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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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
#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=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>1;
		if(check(mid))r=mid;
		else l=mid+1;
	}
	check(l);
	putl(res+(ll)k*l);return 0;
}

你可能感兴趣的:(luogu P5633 最小度限制生成树 wqs二分)