BZOJ 1196 HNOI2006 公路修建问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

 

以上是关于BZOJ 1196 HNOI2006 公路修建问题的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1196 [HNOI2006] 公路修建问题

bzoj 1196: [HNOI2006]公路修建问题

BZOJ_1196_[HNOI2006]公路修建问题_kruskal+二分答案

bzoj1196hnoi2006公路修建问题

BZOJ 1196 HNOI2006 公路修建问题

BZOJ 1196 [HNOI2006]公路修建问题(二分答案+并查集)