您的位置:首页 > 其它

bzoj1196 公路修建 二分+最大生成树

2015-11-28 11:20 363 查看
“花费最多的一条公路的花费尽可能的少”一句话是二分的标志。我们二分花费最多的公路的花费x,然后对于每一条路:如果修建一级公路的费用不大于x,那么就连一条权值为1的边;如果修建二级公路的费用不大于x,就连一条权值为0的边;如果都不能修,就不连边。由于题目中要求所有城市连在一起,而且一级公路要尽可能多,所以我们就跑一遍最大生成树。跑完后,如果发现连不起来或者一级公路的条数小于k,就说明不可行;反之说明可行。
下附AC代码:

#include <cstdio>
#include <cstring>
#define N 12000
#define M 30000
using namespace std;

int x[M],y[M],u[M],v[M],u_[M],v_[M],c1[M],c2[M],n,k,m,fa
;
int getfa(int xx){
if (fa[xx]==xx) return xx;
return fa[xx]=getfa(fa[xx]);
}
int ok(int num){
int sum=0,tot1=0,tot2=0,i;
for (i=1; i<m; i++)
if (c1[i]<=num){ tot1++; u[tot1]=x[i]; v[tot1]=y[i];} else
if (c2[i]<=num){ tot2++; u_[tot2]=x[i]; v_[tot2]=y[i]; }
for (i=1; i<=n; i++) fa[i]=i;
int p,q;
for (i=1; i<=tot1; i++){
p=getfa(u[i]); q=getfa(v[i]);
if (p!=q){ sum++; fa[p]=q; }
}
if (sum<k) return 0;
for (i=1; i<=tot2; i++){
p=getfa(u_[i]); q=getfa(v_[i]);
if (p!=q) fa[p]=q;
}
for (i=2; i<=n; i++)
if (getfa(fa[i])!=getfa(fa[1])) return 0;
return 1;
}
int main(){
scanf("%d%d%d",&n,&k,&m);
int i;
for (i=1; i<m; i++)
scanf("%d%d%d%d",&x[i],&y[i],&c1[i],&c2[i]);
int r,l,mid;
r=1; l=30000;
while (r+1<l){
mid=(r+l)/2;
if (ok(mid)) l=mid; else r=mid+1;
}
if (ok(r)) printf("%d",r); else printf("%d",l);
return 0;
}


2015.2.20
by lych
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: