【bzoj1196】【HNOI2006】【公路修建问题】【并查集】

    xiaoxiao2025-01-20  10

    题目大意

    有一些可修路点对,可修一级或二级公路使图连通且最少有k条一级公路,使最大的公路费用最小。

    解题思路

    可以发现求最大值最小用二分答案,可以用并查集维护当前连通块,首先能建一级公路要先建(满足一级公路的限制),再建二级公路,再看看是否能是整个图连通,直到找到最优答案。

    code

    #include<set> #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #define LL long long #define fo(i,j,k) for(int i=j;i<=k;i++) #define fd(i,j,k) for(int i=j;i>=k;i--) using namespace std; int const maxn=20000; int n,k,m,a[maxn+10],b[maxn+10],c1[maxn+10],c2[maxn+10],father[maxn+10]; int get(int now){ if(!father[now])return now; return father[now]=get(father[now]); } int main(){ freopen("d.in","r",stdin); freopen("d.out","w",stdout); scanf("%d%d%d",&n,&k,&m); fo(i,1,m) scanf("%d%d%d%d",&a[i],&b[i],&c1[i],&c2[i]); int l=1,r=30000; for(;l!=r;){ int mi=(l+r)/2,cnt=0,cnt2=n; memset(father,0,sizeof(father)); fo(i,1,m) if(c1[i]<=mi){ int f1=get(a[i]),f2=get(b[i]); if(f1!=f2){ cnt++; father[f1]=f2; cnt2--; } } fo(i,1,m) if(c2[i]<=mi){ int f1=get(a[i]),f2=get(b[i]); if(f1!=f2){ father[f1]=f2; cnt2--; } } if((cnt>=k)&&(cnt2==1))r=mi; else l=mi+1; } printf("%d",l); return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-1295664.html
    最新回复(0)