HNOI2006公路修建问题

https://www.luogu.org/problemnew/show/P2323

【题目描述】

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条公路,满足上面的条件。

【输入输出格式】

  • 输入格式

第一行有三个数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的花费。

注意,在实际评测时,将只会有 m−1m-1m1 条公路。

  • 输出格式

输出的第一行有一个数据,表示花费最大的公路的花费。

接下来的 n-1行,每行有两个正整数 t和 p , t 和 p 表示在输入的第 t 对(按照输入的顺序,从1开始标号)景点之间修建 p级公路。

n1 条公路的输出必选 t 的大小递增,如果有多个方案使花费最大的公路花费最小,那么输出任意一个都可以。

【输入输出样例】

  • 输入样例
    4 2 5 
    1 2 6 5
    1 3 3 1
    2 3 9 4
    2 4 6 1
  • 输出样例
    6
    1 1
    2 1
    4 2

  本题是一道半裸的模板题,可以有两种做法,看到关键字“最大的最小值”,可以考虑使用二分答案,本篇博客主要讲解第二种方法——最小生成树。

  首先将一级公路和二级公路分别排序,然后从小到大选k条边加入生成树,剩下的边在二级公路中选择。

  

  1 #include
  2 #include
  3 #include
  4 #include
  5 #define maxn 20010
  6 
  7 using namespace std;
  8 
  9 int n,m,k,f[10010],vis[maxn][2];
 10 
 11 struct road
 12 {
 13     int u,v,w,tim;
 14 }e1[maxn],e2[maxn];
 15 
 16 int max(int x,int y)
 17 {
 18     return xy:x;
 19 }
 20 
 21 int getf(int node)
 22 {
 23     if(node==f[node])
 24         return node;
 25     f[node]=getf(f[node]);
 26     return f[node];
 27 }
 28 
 29 void meg(int x,int y)
 30 {
 31     int t1=getf(x),t2=getf(y);
 32     if(t1==t2)
 33         return;
 34     f[t2]=t1;
 35 }
 36 
 37 void qsort(int l,int r,int flag)
 38 {
 39     int i=l,j=r;
 40     if(flag==1)
 41     
 42     {
 43         road mid=e1[(l+r)/2];
 44         do
 45         {
 46             while(e1[i].w;
 47             while(e1[j].w>mid.w)    j--;
 48             if(i<=j)
 49             {
 50                 road t=e1[i];
 51                 e1[i]=e1[j];
 52                 e1[j]=t;
 53                 i++;j--;
 54             }
 55         }while(i<=j);
 56     }    
 57     else 
 58     {
 59         road mid=e2[(l+r)/2];
 60         do
 61         {
 62             while(e2[i].w;
 63             while(e2[j].w>mid.w)    j--;
 64             if(i<=j)
 65             {
 66                 road t=e2[i];
 67                 e2[i]=e2[j];
 68                 e2[j]=t;
 69                 i++;j--;
 70             }
 71         }while(i<=j);
 72     }
 73     if(l<j)    qsort(l,j,flag);
 74     if(i<r)    qsort(i,r,flag);
 75 }
 76 
 77 int main()
 78 {
 79     scanf("%d%d%d",&n,&k,&m);
 80     for(int i=1;i)
 81     {
 82         int x,y,c1,c2;
 83         scanf("%d%d%d%d",&x,&y,&c1,&c2);
 84         e1[i].u=x;e1[i].v=y;e1[i].tim=i;e2[i]=e1[i];
 85         e1[i].w=c1;e2[i].w=c2;
 86     }
 87     qsort(1,m-1,1);
 88     qsort(1,m-1,2);
 89     for(int i=1;i<=n;i++)
 90         f[i]=i;
 91     int num=1,ans=-1;
 92     for(int i=1;i<=k;i++)
 93     {
 94         while(getf(e1[num].u)==getf(e1[num].v))
 95             num++;
 96         meg(e1[num].u,e1[num].v);
 97         vis[e1[num].tim][1]=1;
 98         ans=max(e1[num].w,ans);
 99     }
100     num=1;
101     for(int i=k+1;i)
102     {
103         while(getf(e2[num].u)==getf(e2[num].v))
104             num++;
105         meg(e2[num].u,e2[num].v);
106         vis[e2[num].tim][2]=1;
107         ans=max(e2[num].w,ans);
108     }
109     printf("%d\n",ans);
110     for(int i=1;i)
111     {
112         if(vis[i][1])
113             printf("%d 1\n",i);
114         else if(vis[i][2])
115             printf("%d 2\n",i);
116     }
117     return 0;
118 }

 

你可能感兴趣的:(HNOI2006公路修建问题)