P2323-[HNOI2006]公路修建问题【并查集】
生活随笔
收集整理的這篇文章主要介紹了
P2323-[HNOI2006]公路修建问题【并查集】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
評測記錄:https://www.luogu.org/recordnew/lists?uid=52918&pid=P2323
題目大意
有n個點,m條邊,對于每條邊修二級公路和一級公路修建價格不同(一級比二級貴)。要求留下n-1條邊使其成為一棵樹且至少有k條一級公路,要求最貴的公路價格最小。
解題思路
可以先將一級價格從小到大排序,然后修建k條有用且最小價格的邊。然后剩下的都修二級公路就好了。
code
#include<cstdio> #include<algorithm> #define N 10010 using namespace std; struct node{int x,y,w1,w2,num; }a[2*N]; struct ans_node{int t,ans; }ansr[2*N]; int n,k,m,f[2*N]; bool use[2*N]; int find(int x)//并查集 {return f[x]==x?x:(f[x]=find(f[x]));} void unionn(int x,int y)//連接 {int fa=find(x),fb=find(y);if(fa<fb) f[fa]=fb;else f[fb]=fa; } bool cmp(node x,node y) {return x.w1<y.w1;} bool cmp1(node x,node y) {return x.w2<y.w2;} bool cmp2(ans_node x,ans_node y) {return x.t<y.t;} int main() {scanf("%d%d%d",&n,&k,&m);m--;for(int i=1;i<=m;i++)scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].w1,&a[i].w2),a[i].num=i;for(int i=1;i<=n;i++)f[i]=i;sort(a+1,a+1+m,cmp);int lb=0,ans=0;for(int i=1;i<=m;i++)//修建一級公路{if(find(a[i].x)!=find(a[i].y)){ans=max(ans,a[i].w1);unionn(a[i].x,a[i].y);ansr[++lb].ans=1;use[a[i].num]=true;ansr[lb].t=a[i].num;}if(lb==k) break;}sort(a+1,a+1+m,cmp1);for(int i=1;i<=m;i++)//修建二級公路{if(!use[a[i].num]&&find(a[i].x)!=find(a[i].y)){ans=max(ans,a[i].w2);unionn(a[i].x,a[i].y);use[a[i].num]=true;ansr[++lb].ans=2;ansr[lb].t=a[i].num;}if(lb==n-1) break;}sort(ansr+1,ansr+n,cmp2);printf("%d\n",ans);for(int i=1;i<n;i++)//輸出方案printf("%d %d\n",ansr[i].t,ansr[i].ans); }總結
以上是生活随笔為你收集整理的P2323-[HNOI2006]公路修建问题【并查集】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 积核 IT13 迷你主机开卖:i9-13
- 下一篇: NOIP2018普及组复赛解析