bzoj1196 公路修建 二分+最大生成树

    “花费最多的一条公路的花费尽可能的少”一句话是二分的标志。我们二分花费最多的公路的花费x,然后对于每一条路:如果修建一级公路的费用不大于x,那么就连一条权值为1的边;如果修建二级公路的费用不大于x,就连一条权值为0的边;如果都不能修,就不连边。由于题目中要求所有城市连在一起,而且一级公路要尽可能多,所以我们就跑一遍最大生成树。跑完后,如果发现连不起来或者一级公路的条数小于k,就说明不可行;反之说明可行。

下附AC代码:

#include <cstdio>
#include <cstring>
#define N 12000 
#define M 30000 
using namespace std;
 
int x[M],y[M],u[M],v[M],u_[M],v_[M],c1[M],c2[M],n,k,m,fa[N];
int getfa(int xx){
    if (fa[xx]==xx) return xx;
    return fa[xx]=getfa(fa[xx]);
}
int ok(int num){
    int sum=0,tot1=0,tot2=0,i;
    for (i=1; i<m; i++)
        if (c1[i]<=num){ tot1++; u[tot1]=x[i]; v[tot1]=y[i];} else
        if (c2[i]<=num){ tot2++; u_[tot2]=x[i]; v_[tot2]=y[i]; }
    for (i=1; i<=n; i++) fa[i]=i;
    int p,q;
    for (i=1; i<=tot1; i++){
        p=getfa(u[i]); q=getfa(v[i]);
        if (p!=q){ sum++; fa[p]=q; }
    }
    if (sum<k) return 0;
    for (i=1; i<=tot2; i++){
        p=getfa(u_[i]); q=getfa(v_[i]);
        if (p!=q) fa[p]=q;
    }
    for (i=2; i<=n; i++)
        if (getfa(fa[i])!=getfa(fa[1])) return 0;
    return 1;
}
int main(){
    scanf("%d%d%d",&n,&k,&m);
    int i;
    for (i=1; i<m; i++)
        scanf("%d%d%d%d",&x[i],&y[i],&c1[i],&c2[i]);
    int r,l,mid;
    r=1; l=30000;
    while (r+1<l){
        mid=(r+l)/2;
        if (ok(mid)) l=mid; else r=mid+1;
    }
    if (ok(r)) printf("%d",r); else printf("%d",l);
    return 0;
}


2015.2.20

by lych

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值