$[ HNOI 2006 ] $公路修建問題
阿新 • • 發佈:2018-09-19
ans esp clas algorithm get std define res 還要
\(\\\)
\(Description\)
一個\(N\)個點\(M\)條邊的圖,每條邊可以選擇\(w_i,p_i\)兩個邊權之一,現求一個生成樹上的最大邊權最小值,要求這棵生成樹上至少有\(K\)條邊選擇的是\(w_i\)權值。\(Luogu\)上還要以"選了哪些編號的邊,每條邊選擇的是哪種權值"的形式求輸出方案。
- \(N\in [1,10^4]\),\(M\in [0,2\times 10^4]\),\(K\in [0,N-1]\),\(w_i,p_i\in [1,3\times 10^4]\)
\(\\\)
\(Solution\)
- 最小生成樹變形。先將邊按照\(w_i\)
- 關於輸出方案,每次記錄一下就好,註意第二遍掃描的時候也可能取第一類權值。
\(\\\)
\(Code\)
#include<cmath> #include<cstdio> #include<cctype> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 10010 #define M 20010 #define R register #define gc getchar using namespace std; inline int rd(){ int x=0; bool f=0; char c=gc(); while(!isdigit(c)){if(c=='-')f=1;c=gc();} while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();} return f?-x:x; } int n,m,k,cnt,res,tot; struct edge{int x,y,w1,w2,num;}e[M]; struct result{int p,x;}ans[N]; inline bool cmp1(edge x,edge y){return x.w1<y.w1;} inline bool cmp2(edge x,edge y){return min(x.w1,x.w2)<min(y.w1,y.w2);} inline bool cmp3(result x,result y){return x.p<y.p;} struct UFS{ int f[N]; UFS(){for(R int i=1;i<N;++i) f[i]=i;} int find(int x){return x==f[x]?x:f[x]=find(f[x]);} inline void merge(int x,int y){f[find(x)]=find(y);} inline bool judge(int x,int y){return find(x)==find(y);} }ufs; int main(){ n=rd(); k=rd(); m=rd()-1; for(R int i=1;i<=m;++i){ e[i].x=rd(); e[i].y=rd(); e[i].num=i; e[i].w1=rd(); e[i].w2=rd(); } if(m){ sort(e+1,e+1+m,cmp1); for(R int i=1;i<=m;++i) if(!ufs.judge(e[i].x,e[i].y)){ ufs.merge(e[i].x,e[i].y); ans[++tot].p=e[i].num; ans[tot].x=1; res=max(res,e[i].w1); if((++cnt)==k) break; } } if(cnt<n-1){ sort(e+1,e+1+m,cmp2); for(R int i=1;i<=m;++i) if(!ufs.judge(e[i].x,e[i].y)){ ufs.merge(e[i].x,e[i].y); ans[++tot].p=e[i].num; if(e[i].w1<e[i].w2){ans[tot].x=1;res=max(res,e[i].w1);} else{ans[tot].x=2;res=max(res,e[i].w2);} } } printf("%d\n",res); sort(ans+1,ans+1+tot,cmp3); for(R int i=1;i<=tot;++i) printf("%d %d\n",ans[i].p,ans[i].x); return 0; }
$[\ HNOI\ 2006\ ]\ $公路修建問題