POJ 3013

思路:ans = 每条边(u,v)*v的子树节点的w = 所有的dist[v]*w[v]之和;

#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
#define MAX 500005
const long long int  INF = 100000000000000;
using namespace std;
typedef struct{
    int to, next, w;
}Node;
Node edge[MAX*2];
queue<int>q;
long long int vis[MAX], head[MAX], dist[MAX], W[MAX];
long long int ans;
void init(int n){
    memset(vis, 0, sizeof(vis));
    memset(head, -1, sizeof(head));
    for(int i = 1;i <= n;i ++)
        dist[i] = INF;
    dist[1] = 0;
}
void spfa(int s){
    while(!q.empty()) q.pop();
    q.push(s);
    vis[s] = 1;
    while(!q.empty()){
        int p =q.front();
        q.pop();
        vis[p] = 0;
        for(int i = head[p];i != -1;i = edge[i].next){
            int v = edge[i].to;
            if(dist[v] > dist[p] + edge[i].w){
                dist[v] = dist[p] + edge[i].w;
                if(!vis[v]){
                    q.push(v);
                    vis[v] = 1;
                }
            }
        }
    }
}
void AddEdge(int i, int u, int v, int w){
    edge[i].to = v;
    edge[i].w = w;
    edge[i].next = head[u];
    head[u] = i;
}
int main(){
    int T, n, e, u, v, price, k;
    /* freopen("in.c", "r", stdin); */
    scanf("%d", &T);
    while(T--){
        scanf("%d%d", &n, &e);
        init(n);
        for(int i = 1;i <= n;i ++)
            cin >> W[i]; 
        k = 0;
        for(int i = 0;i < e;i ++){
            scanf("%d%d%d", &u, &v, &price);
            AddEdge(k++, u, v, price);
            AddEdge(k++, v, u, price);
        }
        spfa(1);
        int flag = 0;
        ans = 0LL;
        for(int i = 2;i <= n;i ++){
            if(dist[i] == INF){
                flag = 1;
                break;
            }
            ans += W[i]*dist[i];
        }
        if(!flag) cout << ans << endl;
        else cout << "No Answer
";
    }
    return 0;
}





原文地址:https://www.cnblogs.com/anhuizhiye/p/3933220.html