BZOJ-1196: [HNOI2006]公路修建问题

[文章目录]

Description

OI island有n个旅游景点,不妨将它们从1到n标号。现在,OIER Association需要修公路将这些景点连接起来。一条公路连接两个景点。公路有,不妨称它们为一级公路和二级公路。一级公路上的车速快,但是修路的花费要大一些。 OIER Association打算修n-1条公路将这些景点连接起来(使得任意两个景点之间都会有一条路径)。为了保证公路系统的效率, OIER Association希望在这n-1条公路之中,至少有k条(0≤k≤n-1)一级公路。OIER Association也不希望为一条公路花费的钱。所以,他们希望在满足上述条件的情况下,花费最多的一条公路的花费尽可能的少。而你的任务就是,在给定一些可能修建的公路的情况下,选择n-1条公路,满足上面的条件。1≤n≤10000

二分花费,转化为判定性问题,每次优先选择一级公路,判断是否有k条,再选二级公路,判断图是否联通。

#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 10010 
int n,k,m,fa[N];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
struct edge {
    int x,y,w;
};
bool cmp(const edge &x,const edge &y){return x.w<y.w;}
vector<edge>ed1,ed2;
bool check(int x)
{
    int cnt=0;
    for(int i=1;i<=n;++i) fa[i]=i;
    int now=0,dx,dy;
    while(now<ed1.size()&&ed1[now].w<=x)
    {
        dx=find(ed1[now].x); dy=find(ed1[now].y);
        if(dx!=dy) fa[dy]=dx,cnt++;
        now++;
    }
    if(cnt<k) return false;
    now=0;
    while(now<ed2.size()&&ed2[now].w<=x)
    {
        dx=find(ed2[now].x); dy=find(ed2[now].y);
        if(dx!=dy) fa[dy]=dx,cnt++;
        now++;
    }
    return cnt==n-1;
}
int main()
{
    scanf("%d%d%d",&n,&k,&m); int x,y,w1,w2;
    for(int i=1;i<m;++i)
    {
        scanf("%d%d%d%d",&x,&y,&w1,&w2);
        ed1.push_back((edge){x,y,w1});
        ed2.push_back((edge){x,y,w2});
    }
    sort(ed1.begin(),ed1.end(),cmp);
    sort(ed2.begin(),ed2.end(),cmp);
    int l=1,r=30001,mid;
    while(l<r)
    {
        mid=(l+r)>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }
    printf("%d",r);
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注