b_lg_按位奶牛(預處理點權和邊權)
阿新 • • 發佈:2020-10-14
john走訪完所有的奶牛之後,還要回到他的出發地。
每次路過牧場i的時候,john必須花Ci的時間和奶牛交談,即使之前已經做過工作
請你計算一下,約翰要拆除哪些道路,才能讓談話(忽悠)奶牛的時間變得最少?
知道是MST,但回程難以模擬,故直接將邊權設為:邊權*2+兩個端點的點權
注:由於和起點相連的邊一開始就被加到一個連通塊中,假如起點出度為2,則起點需要被經過3次才對,但kruskal只會算兩次,故還要加上最小的點權(起點的點權)
#include<bits/stdc++.h> using namespace std; const int N=1e5+5, M=1e6+5; int n,m,fa[N],c[N]; struct edge { int u,v,w; }e[M]; int find(int u) {return fa[u]==u ? u : fa[u]=find(fa[u]);} int kruskal() { for (int i=1; i<=n; i++) fa[i]=i; sort(e,e+m,[&](edge a, edge b){return a.w<b.w;}); int ans=0; for (int i=0; i<m; i++) { int fu=find(e[i].u), fv=find(e[i].v); if (fu!=fv) { fa[fu]=fv; ans+=e[i].w; } } return ans; } int main() { std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n>>m; for (int i=1; i<=n; i++) cin>>c[i]; for (int i=0; i<m; i++) cin>>e[i].u>>e[i].v>>e[i].w, e[i].w=2*e[i].w+c[e[i].u]+c[e[i].v]; cout<<*min_element(c+1,c+n+1)+kruskal(); return 0; }
我的疑惑:kruskal不是按照邊權+點權排序的嗎?那約束有兩個啊,萬一和點權很小的點連線的邊權很大(那就不是起點了啊),那這個額外加不就錯了嗎