[bzoj1232]安慰奶牛

先考虑边的代价,容易发现每一条边都需要走两次,也就是2*边权
再考虑点的代价,由于上面的结论,那么就是度数*点权
然后就可以构造新的边权为2*原边权+连接点的点权,然后求最小生成树即可
注意根还有一个点权,所以再加上根(也就是最小点)的点权即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 10005
 4 struct ji{
 5     int x,y,z;
 6 }e[N*10];
 7 int n,m,ans,a[N],f[N];
 8 bool cmp(ji x,ji y){
 9     return x.z<y.z;
10 }
11 int find(int k){
12     if (k==f[k])return k;
13     return f[k]=find(f[k]);
14 }
15 int main(){
16     scanf("%d%d",&n,&m);
17     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
18     ans=a[1];
19     for(int i=2;i<=n;i++)ans=min(ans,a[i]);
20     for(int i=1;i<=m;i++){
21         scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
22         e[i].z=2*e[i].z+a[e[i].x]+a[e[i].y];
23     }
24     sort(e+1,e+m+1,cmp);
25     for(int i=1;i<=n;i++)f[i]=i;
26     for(int i=1;i<=m;i++)
27         if (find(e[i].x)!=find(e[i].y)){
28             f[find(e[i].x)]=find(e[i].y);
29             ans+=e[i].z;
30         }
31     printf("%d",ans);
32 }
View Code

猜你喜欢

转载自www.cnblogs.com/PYWBKTDA/p/11846541.html
今日推荐