[POJ] 3013 Big Christmas Tree

求一棵树,Σ每条边权*子树点权和 最小
转化为,每个节点权值*到根节点的边权和(最小)
spfa最短路
INF一定开大,2^60左右差不多

//Stay foolish,stay hungry,stay young,stay simple
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;

typedef long long ll;

const ll INF=2305843009213693952;
const ll MAXN=200005;

int n,m;

struct Edge{
    int next,to;
    ll w;
}e[MAXN];
int ecnt,head[MAXN];
inline void add(int x,int y,ll w){
    e[++ecnt].next = head[x];
    e[ecnt].to = y;
    e[ecnt].w = w;
    head[x]=ecnt;
}

ll val[MAXN];

bool inq[MAXN];
ll dis[MAXN];
void spfa(){
    queue<int> Q;
    Q.push(1);
    dis[1]=0;
    inq[1]=1;
    while(!Q.empty()){
        int top=Q.front() ;
        Q.pop() ;inq[top]=0;
        for(int i=head[top];i;i=e[i].next){
            int v=e[i].to;
            if(dis[top]!=INF&&dis[v]>dis[top]+e[i].w){
                dis[v]=dis[top]+e[i].w;
                if(!inq[v]) Q.push(v),inq[v]=1; 
            }
        }
    } 
}

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        ecnt=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) head[i]=0;
        for(int i=1;i<=n;i++){
            scanf("%lld",&val[i]);
        }
        for(int i=1;i<=m;i++){
            int x,y;
            ll w;
            scanf("%d%d%lld",&x,&y,&w);
            add(x,y,w);
            add(y,x,w);
        }
        for(int i=1;i<=n;i++) dis[i]=INF;
        spfa();
        ll ans=0;
        bool success=1;
        for(int i=1;i<=n;i++){
            if(dis[i]==INF){
                success=0;
                break;
            }
            ans+=dis[i]*val[i];
        }
        if(success) printf("%lld
",ans);
        else printf("No Answer
");
    }
    return 0;
}

本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9247474.html

原文地址:https://www.cnblogs.com/ghostcai/p/9247474.html