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不是按照边权+点权排序的吗?那约束有两个啊,万一和点权很小的点连接的边权很大(那就不是起点了啊),那这个额外加不就错了吗