[題解](最小生成樹)luogu_P2916安慰奶牛

Posted superminivan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[題解](最小生成樹)luogu_P2916安慰奶牛相关的知识,希望对你有一定的参考价值。

可以發現每個點經過次數恰好等於這個點的度數,所以把點權下放邊權,跑最小生成樹,原來邊權乘二在加上兩端點權,答案再加一遍起點最小點權

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=10010;
const int maxm=100010;
int n,m;
ll ans;
struct node{
    int u,v,w,nxt;
    bool operator <(const node&a)const{
        return w<a.w;
    }
}e[maxm*2];
int head[maxn],cnt,w[maxn];
int fa[maxn];
int find(int x){
    while(x!=fa[x])x=fa[x]=fa[fa[x]];return x;
}
void add(int u,int v,int ww){
    e[++cnt].v=v;e[cnt].u=u;e[cnt].w=ww;e[cnt].nxt=head[u];head[u]=cnt;
    e[cnt].w=(e[cnt].w*2)+w[u]+w[v];
}
void kruskal(){
    for(int i=1;i<=n;i++)fa[i]=i;
    sort(e+1,e+1+cnt);
    for(int i=1;i<=cnt;i++){
        int x=find(e[i].u),y=find(e[i].v),z=e[i].w;
        if(x==y)continue;
        fa[x]=y;
        ans+=z;
    }
}
int main(){
    scanf("%d%d",&n,&m);int minn=0x7fffffff;
    for(int i=1;i<=n;i++)scanf("%d",&w[i]),minn=min(minn,w[i]);
    for(int i=1,u,v,w;i<=m;i++){
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
//        add(v,u,w);
    }
    kruskal();
    printf("%lld",ans+minn);
}

 

以上是关于[題解](最小生成樹)luogu_P2916安慰奶牛的主要内容,如果未能解决你的问题,请参考以下文章

[題解](二分答案/單調隊列)luogu_P1419尋找段落

[題解]luogu_P1144最短路計數

[題解](單調隊列dp)luogu_P1725琪露諾

[題解](水/數學)luogu_P1147連續自然數和

[題解](貪心/堆)luogu_P2107小Z的AK計劃

题解P2916 [USACO08NOV]安慰奶牛Cheering up the Cow-C++