• 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<bitsstdc++.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
    ",x)
    #define putl(x) printf("%lld
    ",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;
    }
    
  • 相关阅读:
    【算法研究】排序算法
    20121031 学习心得与体会
    循环有序数组查找(log(n))
    XmlDocument创建XML文档
    GCC地址对齐的2个方法
    打印getaddrinfo()返回的地址信息
    Java单例模式
    二叉搜索树的例子BST
    XmlTextWriter创建XML文档
    XmlDocument读取XML文档
  • 原文地址:https://www.cnblogs.com/chdy/p/13222879.html
Copyright © 2020-2023  润新知