• BZOJ1196 [HNOI2006] 公路修建问题


    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1196

    Description

    OI island是一个非常漂亮的岛屿,自开发以来,到这儿来旅游的人很多。然而,由于该岛屿刚刚开发不久,所以那里的交通情况还是很糟糕。所以,OIER Association组织成立了,旨在建立OI island的交通系统。 OI island有n个旅游景点,不妨将它们从1到n标号。现在,OIER Association需要修公路将这些景点连接起来。一条公路连接两个景点。公路有,不妨称它们为一级公路和二级公路。一级公路上的车速快,但是修路的花费要大一些。 OIER Association打算修n-1条公路将这些景点连接起来(使得任意两个景点之间都会有一条路径)。为了保证公路系统的效率, OIER Association希望在这n-1条公路之中,至少有k条(0≤k≤n-1)一级公路。OIER Association也不希望为一条公路花费的钱。所以,他们希望在满足上述条件的情况下,花费最多的一条公路的花费尽可能的少。而你的任务就是,在给定一些可能修建的公路的情况下,选择n-1条公路,满足上面的条件。

    Input

    第一行有三个数n(1≤n≤10000),k(0≤k≤n-1),m(n-1≤m≤20000),这些数之间用空格分开。 N和k如前所述,m表示有m对景点之间可以修公路。以下的m-1行,每一行有4个正整数a,b,c1,c2 (1≤a,b≤n,a≠b,1≤c2≤c1≤30000)表示在景点a与b 之间可以修公路,如果修一级公路,则需要c1的花费,如果修二级公路,则需要c2的花费。

    Output

    一个数据,表示花费最大的公路的花费。

    这道题貌似之前的某一次NOIP模拟赛有,终于学会了……

    二分最大边即可

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #define rep(i,l,r) for(int i=l; i<=r; i++)
     6 #define clr(x,y) memset(x,y,sizeof(x))
     7 #define travel(x) for(Edge *p=last[x]; p; p=p->pre)
     8 using namespace std;
     9 const int INF = 0x3f3f3f3f;
    10 const int maxn = 10010;
    11 inline int read(){
    12     int ans = 0, f = 1;
    13     char c = getchar();
    14     for(; !isdigit(c); c = getchar())
    15     if (c == '-') f = -1;
    16     for(; isdigit(c); c = getchar())
    17     ans = ans * 10 + c - '0';
    18     return ans * f;
    19 }
    20 struct Edge{
    21     int from,to,c1,c2;
    22 }edge[20010];
    23 int n,m,k,cnt=0,fa[maxn];
    24 int getfa(int x){
    25     return x == fa[x] ? x : fa[x] = getfa(fa[x]);
    26 }
    27 bool judge(int x){
    28     rep(i,1,n) fa[i] = i;
    29     int cnt = 0;
    30     rep(i,1,m-1){
    31         if (edge[i].c1 > x) continue;
    32         int a = getfa(edge[i].from); int b = getfa(edge[i].to);
    33         if (a != b){
    34             fa[a] = b; cnt++;
    35         }
    36     }
    37     if (cnt < k) return 0;
    38     rep(i,1,m-1){
    39         if (edge[i].c2 > x) continue;
    40         int a = getfa(edge[i].from); int b = getfa(edge[i].to);
    41         if (a != b){
    42             fa[a] = b; cnt++;
    43         }
    44     }
    45     if (cnt < n-1) return 0;
    46     return 1;
    47 }
    48 int main(){
    49     n = read(); k = read(); m = read();
    50     rep(i,1,m-1){
    51         edge[++cnt].from = read(); edge[cnt].to = read();
    52         edge[cnt].c1 = read(); edge[cnt].c2 = read();
    53     }
    54     int l = 1, r = 30000, ans;
    55     while (l <= r){
    56         int mid = (l + r) >> 1;
    57         if (judge(mid)) ans = mid, r = mid - 1;
    58         else l = mid + 1;
    59     }
    60     printf("%d
    ",ans);
    61     return 0;
    62 }
    View Code
  • 相关阅读:
    八张图读懂未来“互联网+”的六大趋势
    跑一段代码遍历所有汉字
    PHP业务逻辑层和数据访问层设计
    漫谈社区PHP 业务开发
    以Apache服务器、php语言为例 详解动态网站的访问过程
    sublime text
    《产品经理的20堂必修课》
    检测文件是否有bom头
    利用开源框架Volley来下载文本和图片。
    往SD卡中写文件的方法。
  • 原文地址:https://www.cnblogs.com/jimzeng/p/bzoj1196.html
Copyright © 2020-2023  润新知