【bzoj1196】[HNOI2006]公路修建问题

二分答案
验证有一种贪心的思想,就是如果这条路的c1比二分的值还小,那就要果断选择一级公路。
搜过一遍后,如果可供选择的一级公路小于k,就可以直接返回否了。
接下来继续选择,如果可以选到n-1条路,就可以,否则就不可以。
选择道路时,选择的一定是不在一个集合里及不连通的,要用并查集优化。
 
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
 
#define N 100010
 
struct Node
{
    int x,y,c1,c2;
}a[N<<2];
 
int n,k,m;
int f[N];
 
int find(int x)
{
    return x==f[x] ? f[x] : f[x]=find(f[x]);
}
 
int work(int d)
{
    int ans=0;
    for (int i=1;i<=n;i++)
        f[i]=i;
    for (int i=1;i<=m;i++)
        if (a[i].c1<=d)
        {
            int r1=find(a[i].x),r2=find(a[i].y);
            if (r1!=r2)
                f[r1]=r2,ans++;
        }
    if (ans<k)
        return false;
    for (int i=1;i<=m;i++)
        if (a[i].c2<=d)
        {
            int r1=find(a[i].x),r2=find(a[i].y);
            if (r1!=r2)
                f[r1]=r2,ans++;
        }
    if (ans==n-1)
        return true;
    else
        return false;
}
 
int main()
{
    scanf("%d%d%d",&n,&k,&m);
    for (int i=1;i<=m;i++)
        scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].c1,&a[i].c2);
    int l=0,r=N;
    while (l<r)
    {
        int mid=(l+r)>>1;
        if (work(mid))
            r=mid;
        else
            l=mid+1;
    }
    if (work(l))
        printf("%d",l);
    else
        printf("%d",r);
    return 0;
}

  

posted @ 2016-03-25 20:55  Yangjiyuan  阅读(171)  评论(0编辑  收藏  举报