bzoj1196[HNOI2006]公路修建问题

bzoj1196[HNOI2006]公路修建问题

题意:

修n-1条公路将n个点连通,每个点可建一级公路也可建二级公路,要求一级公路必须有k条,要求花费最多的公路花费最少。

题解:

首先二分最大花费,接着判定:先在不产生环的前提下(用并查集维护)让每条路尽量修一级公路,如果最后无法构成树则考虑修二级公路。

代码:

 1 #include <cstdio> 
 2 #include <cstring>
 3 #include <algorithm>
 4 #define inc(i,j,k) for(int i=j;i<=k;i++)
 5 #define maxn 10500
 6 using namespace std;
 7 
 8 int n,k,m,u[maxn*2],v[maxn*2],c1[maxn*2],c2[maxn*2],mx,fa[maxn],cnt;
 9 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
10 bool check(int lim){
11     inc(i,1,n)fa[i]=i; cnt=0;
12     inc(i,1,m)if(c1[i]<=lim){
13         int x=find(u[i]),y=find(v[i]); if(x==y)continue; fa[y]=x; cnt++;
14     }
15     if(cnt<k)return 0;
16     inc(i,1,m)if(c2[i]<=lim){
17         int x=find(u[i]),y=find(v[i]); if(x==y)continue; fa[y]=x; cnt++;
18     }
19     if(cnt<n-1)return 0; return 1;
20 }
21 int main(){
22     scanf("%d%d%d",&n,&k,&m); mx=0;
23     inc(i,1,m-1)scanf("%d%d%d%d",&u[i],&v[i],&c1[i],&c2[i]),mx=max(mx,c1[i]),mx=max(mx,c2[i]);
24     int l=0,r=mx,ans;
25     while(l<=r){
26         int mid=(l+r)>>1;
27         if(check(mid))ans=mid,r=mid-1;else l=mid+1;
28     }
29     printf("%d",ans); return 0;
30 }

20160531

posted @ 2016-07-20 19:07  YuanZiming  阅读(620)  评论(0编辑  收藏  举报