码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1196 HNOI2006 公路修建问题

时间:2017-09-08 21:43:22      阅读:103      评论:0      收藏:0      [点我收藏+]

标签:span   div   sort   std   algorithm   include   zoj   bzoj   需要   

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

如果去掉所谓的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 公路修建问题

标签:span   div   sort   std   algorithm   include   zoj   bzoj   需要   

原文地址:http://www.cnblogs.com/OIerLYF/p/7496225.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!