P2323 [HNOI2006]公路修建问题 (二分)

二分最小值,能选第一个尽量选,之后选第二个看看能否满足答案

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+10;
const int mod=1e7+7;
int n,m,k;
struct node{
    int a,b;
    ll c1,c2;
}s[N];
int p[N];
int ans[N];
int st[N];
int find(int x){
    if(p[x]!=x){
        p[x]=find(p[x]);
    }
    return p[x];
}
bool check(int x){
    int i;
    for(i=1;i<=n;i++)
        p[i]=i;
    memset(st,0,sizeof st);
    int cnt=0;
    for(i=1;i<=m;i++){
        int pa=find(s[i].a);
        int pb=find(s[i].b);
        if(s[i].c1<=x){
            if(pa!=pb){
                cnt++;
                p[pa]=pb;
                st[i]=1;
            }
        }
    }
    int d=0;
    for(i=1;i<=m;i++){
        int pa=find(s[i].a);
        int pb=find(s[i].b);
        if(s[i].c2<=x){
            if(pa!=pb){
                d++;
                p[pa]=pb;
                st[i]=2;
            }
        }
    }
    if(cnt>=k&&(cnt+d)==n-1){
        for(i=1;i<=m;i++){
            ans[i]=st[i];
        }
        return true;
    }
    return false;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>k>>m;
    int i;
    m--;
    for(i=1;i<=m;i++){
        int a,b,c,d;
        cin>>a>>b>>c>>d;
        s[i]={a,b,c,d};
    }
    int l=1,r=30000;
    while(l<r){
        int mid=l+r>>1;
        if(check(mid))
            r=mid;
        else
            l=mid+1;
    }
    cout<<l<<endl;
    for(i=1;i<=m;i++){
        if(ans[i])
            cout<<i<<" "<<ans[i]<<endl;
    }
    return 0;
}
View Code

 

posted @ 2020-08-21 16:06  朝暮不思  阅读(114)  评论(0编辑  收藏  举报