BZOJ 1232 安慰奶牛题解

题目传送门:BZOJ 1232

这是一个边权和点权结合在一起的题,但是因为要从当前点出发并回到原点,所以每个边都被经过了两次,节点至少被经过一次,所以我们将边权重新赋值,所以推出

 

那么遍历之后,并不是最终结果,我们有个根节点未选择,所以对于当前这个树,我们可以寻找一个最小的点权来作为根节点,那么他会被多经过一次,加上即使最后答案;

所以就是修改边权跑最小生成树;

这里我作了kruskal做法:

#include
using namespace std; int a[10001]; struct edge { int l,r,v; } e[100001]; int f[10001]; bool cmp(edge a,edge b) { return a.vint n,ans; int find(int n) { if(f[n]==n) return n; f[n]=find(f[n]); return f[n]; } void bing(int m,int n) { int x,y; x=find(m); y=find(n); f[x]=y; } int main() { int p,num=0,k=0,s=0x7fffffff; scanf("%d%d",&n,&p); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); s=min(s,a[i]); } for(int i=1;i<=p;i++) { num++; scanf("%d%d%d",&e[num].l,&e[num].r,&e[num].v); e[num].v=e[num].v*2+a[e[num].l]+a[e[num].r]; } sort(e+1,e+num+1,cmp); for(int i=1;i<=n;i++) f[i]=i; for(int i=1;k-1;i++) { if(find(e[i].l)!=find(e[i].r)) { ans+=e[i].v; bing(e[i].l,e[i].r); k++; } } printf("%d",ans+s); return 0; }

转载于:https://www.cnblogs.com/Tyouchie/p/10366912.html

你可能感兴趣的:(BZOJ 1232 安慰奶牛题解)