bzoj1196: [HNOI2006]公路修建问题

题目链接

bzoj1196: [HNOI2006]公路修建问题

题解

二分,判断能否连通

代码

#include<vector> 
#include<cstdio> 
#include<cstring> 
#include<algorithm> 
#define LL long long
inline int read() { 
    int x = 0,f = 1;char c = getchar(); 
    while(c < '0'||c > '9')c = getchar(); 
    while(c <= '9' &&c >= '0')x = x * 10 + c - '0',c = getchar(); 
    return x * f; 
} 
 
int n,K,m,Ans;
int fa[10005];
struct Edge{int x,y,c1,c2;}e[20005]; 
int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]);} 
int use[20007]; 
bool check(int x) { 
    for(int i = 1;i <= n;++ i) fa[i] = i; 
    memset(use,0,sizeof use);  
    int cnt = 0;  
    for(int i = 1;i <= m;++ i) { 
        if(e[i].c1 > x) continue; 
        int fx = find(e[i].x),fy = find(e[i].y);  
        if(fx != fy)  fa[fx] = fy,cnt ++, use[i] = 1; 
    } 
    if(cnt < K) return 0; 
    for(int i = 1;i <= m;++ i) { 
        if(e[i].c2 > x || use[i]) continue; 
        int fx = find(e[i].x),fy = find(e[i].y); 
        if(fx != fy) fa[fx] = fy,cnt ++,use[i] = 2; 
        if(cnt == n - 1)break; 
    } 
    if(cnt != n-1) return false; 
    return true; 
} 
int ans[20007]; 
int main() { 
    n = read(),K = read(),m = read(); 
    for(int i = 1;i < m;++ i)  
        e[i].x = read(),e[i].y = read(),e[i].c1 = read(),e[i].c2 = read(); 
    int l = 1,r = 30000; 
    while(l <= r) { 
        int mid = l + r >> 1; 
        if(check(mid)) { 
            for(int i = 1;i < m;++ i)ans[i] = use[i]; 
            Ans = mid,r = mid - 1; 
        } 
        else l = mid + 1; 
    } 
    printf("%d",Ans); 
    puts(""); 
    //for(int i = 1;i < m;++ i) 
    //  if(ans[i]) printf("%d %d\n",i,ans[i]); 
    return 0; 
} 
posted @ 2018-07-05 19:53  zzzzx  阅读(108)  评论(0编辑  收藏  举报