日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Luogu T16048 会议选址

發布時間:2023/12/18 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 会议选址的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。