BZOJ 2654: tree

10 篇文章 0 订阅
5 篇文章 0 订阅

(男神跟我说这题很搞笑.......

二分给白边都加上一个权 不难证明这对MST上白边的数量影响是由二分性的
排序的时候如果权值相等就让白边在前面
这样的话二分出来 记录个数恰好>=need时的答案就可以了

至于为什么 挺值得思考。。 因为保证有解 所以可以让相等权值的黑边代替白边
其它对二分的理解 解释跟上面说的大同小异 可以自己YY一下

其实我不是很会证为什么这样做是对的 以自己的理解讲一下吧
因为kruskal的贪心性保证了最优 所以就用二分来调整MST中白边的个数

#include<bits/stdc++.h>
#define me(a,x) memset(a,x,sizeof a)
using namespace std;
inline int read(){
    char ch=getchar(); int x=0;
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0'; ch=getchar();}
    return x;
}
struct E{int x,y,c,d;}a[100005];
int Cmp(E x,E y){return x.c!=y.c?(x.c<y.c):(x.d<y.d);}
int n,m,d,f[50005];
inline int fa(int x){return x==f[x]?x:f[x]=fa(f[x]);}
int main()
{
    n=read(),m=read(),d=read();
    int i,l=-100,r=100;
    for(i=1;i<=m;i++)a[i]=(E){read()+1,read()+1,read(),read()};
    int ans,s,t,u,x,y;
    while(l<=r){
        int mid=(l+r)>>1;
        for(i=1;i<=n;i++)f[i]=i;
        for(i=1;i<=m;i++)if(!a[i].d)a[i].c+=mid;
        sort(a+1,a+1+m,Cmp);
        s=t=u=0;
        for(i=1;i<=m;i++){
            x=fa(a[i].x),y=fa(a[i].y);
            if(x==y)continue;
            t++,f[x]=y,s+=a[i].c,u+=!a[i].d;
            if(t==n-1)break;
        }
        if(u>=d)ans=s-d*mid,l=mid+1; else r=mid-1;
        for(i=1;i<=m;i++)if(!a[i].d)a[i].c-=mid;
    }
    printf("%d\n",ans);
    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值