分析:最小生成树的一个变形。首先,最终必定是一颗树,先随便画一颗树然后自己模拟走一遍,会发现应该把连接某条边的2个顶点的权值加入到边权中,且边权应该乘2,所以最终以2l+point1+point2为边权生成最小生成树即可,至于起点在哪都不影响,只是因为睡前还要安慰一遍睡觉的顶点的奶牛(即起点的奶牛)所以选出最小的ci即可。
直接上代码:
#include<cstdio> //安慰奶牛 蓝桥 最小生成树
#include<algorithm>
using namespace std;
#define Max 100000+5
struct Edge
{
int from, to, cost;
}e[Max];
int n, m, c[Max];
int father[Max];
int ans, minn = 0x3f3f3f3f;
bool cmp(Edge &a,Edge &b)
{
return a.cost < b.cost;
}
int find(int x)
{
if (father[x] == x) return x;
return father[x] = find(father[x]);
}
int main()
{
scanf("%d%d", &n,&m);
for (int i = 1; i <= n; i++)
{
scanf("%d", c + i);
father[i] = i;
minn = min(minn, c[i]);
}
for (int i = 1; i <= m; i++)
{
scanf("%d%d%d", &e[i].from, &e[i].to, &e[i].cost);
e[i].cost = 2 * e[i].cost + c[e[i].from] + c[e[i].to];
}
sort(e + 1, e + m + 1, cmp);
for (int i = 1; i <= m; i++)
{
int fx = find(e[i].from);
int fy = find(e[i].to);
if (fx != fy)
{
father[fx] = fy;
ans += e[i].cost;
}
}
printf("%d\n", ans + minn);
return 0;
}