Luogu T16048 会议选址
本題idea版權來自CSDN博客Steve_Junior的醫院設置2。
并沒有什么用的鏈接
題目背景
\(A\)國的國情十分獨特。它總共有\(n\)個城市,由\(n-1\)條道路連接。國內的城市當然是連通的。
時隔多年,全國會議再次召開。全國人民歡欣雀躍,期待會議后國家發展揭開新篇章。然而,會議籌備組此時卻在為會議選址問題頭痛不已。
題目描述
為了響應“保護環境”的國策,中央決定不再將首都作為固定會址,而是先計算出全國每個城市參會代表人數\(p_i\),若將城市u作為會址,定義城市v的出行開銷為\(C_{v}=p_{v}*dis_{u,v}\)。會議籌備組的任務是選定一個城市\(u\),使出行總開銷\(\sum_{i=1}^{n}C_{i}\)最小。
輸入格式
第一行一個數字\(n\),表示城市總數。
第二行\(n\)個數字,表示每個城市參會代表人數。
第三行至第\(n+2\)行,每行三個數字\(u,v,w\),表示一條權值為\(w\)的連接城市\(u\)與城市\(v\)的道路。
輸出格式
一個數字,表示最小出行總開銷。
數據范圍
對于30%的數據,\(n\leq 200\)。
對于50%的數據,\(n\leq 1500\)。
對于100%的數據,\(n\leq 5\times 10^{5},1\leq w\leq 10^{4}\)。
題解
30分做法
floyd暴力求出任意點對之間的距離,枚舉每個城市作為會址,計算出總開銷之后取最小值。大概5分鐘就可以寫完。復雜度為\(O(n^3)\)。這也是對拍時std采用的做法。
50分做法
將暴力求任意點對之間距離的算法改為\(n\)次堆優化dijkstra算法就可以通過。或者也可以采用一遍DFS后暴力查詢\(O(n^2)\)次LCA的做法。其實是為了強行湊部分分才這樣設計的
100分做法
這個做法十分玄妙其實只是自己一開始nc了而已……。
下面到了精彩的猜結論時間
理性分析畫圖發現會址其實就是樹的帶權重心,與邊權無關。
貼一個來自學弟的證明:
考慮這棵樹中的某一條邊\((u,v)\),判斷\(u\)和\(v\)哪個作為會址更優。可以看成城市\(u\)一側的代表已經全部轉移至城市\(u\),城市\(v\)也是如此。此時不難發現,將會址設在兩個城市中此時所處代表更多的那個城市,總開銷是最小的。因此,每次會址向更優的方向調整時就會不斷向樹的帶權重心靠近,最后帶權重心就是會址。
帶權重心的求法其實和不帶權的沒有什么區別。將節點數改成代表數就可以了。
找到帶權重心之后,接下來的任務變成了快速求出總開銷。這個可以用簡單的樹形DP實現。
以重心為全樹的根節點,設計狀態\(f_i\)為將以\(i\)為根節點的子樹中所有節點轉移至節點\(i\)的總開銷,最后\(f_{root}\)就是答案。轉移時,記\(v\rightarrow u\)為v是u的子節點,則\(f_{u}=\sum\limits_{v\rightarrow u}(f_{v}+size_{v}\cdot w_{u,v})\)。可以看作將已經轉移至\(v\)的所有代表經過邊\((u,v)\)轉移至\(u\)。
代碼
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+10,maxm=2e5+10,inf=0x7fffffff; int heade[maxn],dw[maxn],ev[maxm],ew[maxm],nexte[maxm]; int size[maxn],f[maxn],cost[maxn]; int n,tot=0,root,sum=0; void add_edge(int u,int v,int w){ev[++tot]=v;ew[tot]=w;nexte[tot]=heade[u];heade[u]=tot;} void getroot(int ui,int fa) {int i,vi;size[ui]=dw[ui];f[ui]=0;for(i=heade[ui];~i;i=nexte[i]){vi=ev[i];if(vi==fa){continue;}getroot(vi,ui);size[ui]+=size[vi];f[ui]=max(f[ui],size[vi]);}f[ui]=max(f[ui],sum-size[ui]);if(f[ui]<f[root]){root=ui;} } void dfs(int ui,int fa) {int i,vi,wi;size[ui]=dw[ui];cost[ui]=0;for(i=heade[ui];~i;i=nexte[i]){vi=ev[i];wi=ew[i];if(vi==fa){continue;}dfs(vi,ui);size[ui]+=size[vi];cost[ui]+=cost[vi]+size[vi]*wi;} } int main() {int i,j,u,v,w;//freopen("data.in","r",stdin);//freopen("test.out","w",stdout);cin>>n;memset(heade,-1,sizeof(heade));for(i=1;i<=n;i++){scanf("%d",&dw[i]);sum+=dw[i];}for(i=1;i<n;i++){scanf("%d%d%d",&u,&v,&w);add_edge(u,v,w);add_edge(v,u,w);}root=0;f[0]=inf;getroot(1,0);dfs(root,0);cout<<cost[root];return 0; }轉載于:https://www.cnblogs.com/XSC637/p/7781058.html
總結
以上是生活随笔為你收集整理的Luogu T16048 会议选址的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Third week-homework(
- 下一篇: 出栈顺序 与 卡特兰数(Catalan)