BZOJ 1196 HNOI2006 公路修建问题

一眼可以看出来最小生成树,但需要仔细思考。

如果去掉所谓的1级公路数量限制,单独思考 “花费最多的一条公路的花费尽可能的少”这个问题。

那么毫无疑问的需要二分。

多了一个1级公路,算法只需要吧1级公路和2级公路分开跑最小生成树就可以了。

#include <cstdio>
#include <algorithm>
#include <cstring>
 
struct node{
    int u,v,w1,w2;
}Edge[52222];
 
int fa[12222];
int n,m,k,l=0,r=50000,mid;
int x,y,w1,w2;
 
 
 
bool CMP1(const node &a,const node &b){
    return a.w1<b.w1;
}
 
bool CMP2(const node &a,const node &b){
    return a.w2<b.w2;
}
 
int findfa(int x){
    if(fa[x]!=x) return fa[x]=findfa(fa[x]);
    return fa[x];
}
 
 
bool Can(int x){
    std::sort(Edge+1,Edge+m,CMP1);
    int tot = 0;
    for(int i=1;tot<k;i++){
        if(Edge[i].w1 > x || i > m-1) return false;
        int fx = findfa(Edge[i].u);
        int fy = findfa(Edge[i].v);
        if(fx!=fy){
            fa[fx]=fy;
            tot++;
        }
    }
    std::sort(Edge+1,Edge+m,CMP2);
    tot = 0;
    for(int i=1;tot<n-k-1;i++){
        if(Edge[i].w2 > x || i > m-1) return false;
        int fx = findfa(Edge[i].u);
        int fy = findfa(Edge[i].v);
        if(fx!=fy){
            fa[fx]=fy;
            tot++;
        }
    }
    return true;
}
 
int main(){
    scanf("%d%d%d",&n,&k,&m);
    for(int i=1;i<m;++i){
        scanf("%d%d%d%d",&x,&y,&w1,&w2);
        Edge[i].u=x;
        Edge[i].v=y;
        Edge[i].w1=w1;
        Edge[i].w2=w2;
    }
    while(l<r){
        for(int i=1;i<=n;i++) fa[i]=i;
        mid = (l+r)>>1;
        if( Can(mid) ) r=mid;
        else l = mid+1;
     
    }
    printf("%d\n",l);
    return 0;
}

 

转载于:https://www.cnblogs.com/OIerLYF/p/7496225.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值