POJ-3013 Big Christmas Tree[最短路变形]

POJ-3013 Big Christmas Tree[最短路]

题目链接

POJ - 3013 Big Christmas Tree

要写题解的时候发现有一篇很久之前写到一半的(没错就是这个)

题目描述

  Christmas is coming to KCM city. Suby the loyal civilian in KCM city is preparing a big neat Christmas tree. The simple structure of the tree is shown in right picture.

  The tree can be represented as a collection of numbered nodes and some edges. The nodes are numbered \(1\) through \(n\). The root is always numbered \(1\). Every node in the tree has its weight. The weights can be different from each other. Also the shape of every available edge between two nodes is different, so the unit price of each edge is different. Because of a technical difficulty, price of an edge will be (sum of weights of all descendant nodes) × (unit price of the edge).

  Suby wants to minimize the cost of whole tree among all possible choices. Also he wants to use all nodes because he wants a large tree. So he decided to ask you for helping solve this task by find the minimum cost.

Input

  The input consists of \(T\) test cases. The number of test cases \(T\) is given in the first line of the input file. Each test case consists of several lines. Two numbers \(v\), \(e\) (\(0 \leq v\), \(e \leq 50000\)) are given in the first line of each test case. On the next line, \(v\) positive integers \(w_i\) indicating the weights of \(v\) nodes are given in one line. On the following \(e\) lines, each line contain three positive integers \(a\), \(b\), \(c\) indicating the edge which is able to connect two nodes \(a\) and \(b\), and unit price \(c\).

  All numbers in input are less than \(2^{16}\).

Output

  For each test case, output an integer indicating the minimum possible cost for the tree in one line. If there is no way to build a Christmas tree, print “No Answer” in one line.

Sample

Sample Input Sample Output
2
2 1
1 1
1 2 15
7 7
200 10 20 30 40 50 60
1 2 1
2 3 3
2 4 2
3 5 4
3 7 2
3 6 3
1 5 9
15
1210

题目分析

题目大意:
现在要装饰一颗圣诞树,这个圣诞树有\(n\)个点,每个点都有一个点权,相连两点的一条边有边权。每连接两点(即连通一条边)所要的花费 = 所有子代点的点权 * 这条边的边权。 已知这棵树一定是以\(1\)为树的根,现在要计算装饰圣诞树的最小花费。

分析:
所要的花费 = 所有子代点的点权 * 这条边的边权。
也就是说每个点的代价 = 该点的点权 * 从该点到\(1\)(根节点)的最短路径这条边的边权
一开始没看题目给的图瞎猜样例二怎么走的,\(Orz\)一直没想通。
第二个样例见题目给的图可以知道(猜到
\(res = (1+3+4)*40+(1+3+2)*50+(1+3+3)*60+(1+3)*20+(1+2)*30+(1)*10\)
因此只要写最短路计算每个点到\(1\)的最短路径,再乘以每个点的权值,求和即可

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <bitset>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <set>
#include <map>

#define  endc       std::ios::sync_with_stdio(false); // 关掉c++流
#define  INOPEN     freopen("in.txt", "r", stdin)
#define  OUTOPEN    freopen("out.txt", "w", stdout)
#define  mes(a, b)  memset(a, b, sizeof(a))
#define  isdigit(a) ((a)>='0'&&(a)<='9')
#define  xiao(a)    (a)>='a'&&(a)<='z'
#define  da(a)      (a)>='A'&&(a)<='Z'
#define  pii        pair<int, int>
#define  lowbit(x)  x & (-x)
#define  fi         first
#define  se         second
#define  lson       id<<1
#define  rson       id<<1|1

typedef unsigned long long int ull;
typedef long long int ll;
const double eps  = 1e-8;
const double pi   = acos(-1.0);
const int    inf  = 0x3f3f3f3f;
const ll     INF  = 1e18 + 8;
const int    maxm = 2e5 + 6;
const int    maxn = 2e5 + 10;
const int    mod  = 100000009;
using namespace std;

inline int read() {
    int x = 0, f = 1; char ch = getchar();
    while(!isdigit(ch)){if(ch == '-') f = -f; ch = getchar();}
    while(isdigit(ch)){x = (x<<3)+(x<<1)+ch-'0'; ch = getchar();}
    return x * f;
}

struct node {
    int v, next; ll w;
    node() {}
    node(int v, int n, ll w) : v(v), next(n), w(w) {}
}edge[maxm << 1];
ll dis[maxn], a[maxn];
int head[maxn];
bool vis[maxn];
int tol, n;

void add(int u, int v, ll w) {
    edge[tol] = node(v, head[u], w);  head[u] = tol++;
}

void init() {
    tol = 0;
    mes(head, -1);  mes(vis, false);
    for(int i = 0; i < maxn; ++i)   dis[i] = INF;
}

ll spfa(int s, int t) {
    queue<int> q;
    while(!q.empty()) q.pop();
    dis[s] = 0, vis[s] = true;
    q.push(s);
    while(!q.empty()) {
        int u = q.front(); q.pop();
        vis[u] = false;
        for(int i = head[u]; ~i; i = edge[i].next) {
            node &e = edge[i];
            if(dis[e.v] > dis[u] + e.w) {
                dis[e.v] = dis[u] + e.w;
                if(vis[e.v])    continue;
                vis[e.v] = true;
                q.push(e.v);
            }
        }
    }
    return dis[t];
}

int main() {
    int T;
    // INOPEN;
    // OUTOPEN;
    scanf("%d", &T);
    while(T--) {
        init();
        int n, m, u, v; ll w;
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
        while(m --) {
            scanf("%d%d%lld", &u, &v, &w);
            add(u, v, w);
            add(v, u, w);
        }
        spfa(1, n);
        ll ans = 0; int flag = 0;
        for(int i = 2; i <= n; ++i) {
            if(dis[i] == INF) {
                flag = 1;
                break;
            }
            // cout << i <<" " << dis[i] << endl;
            ans += dis[i] * a[i];
        }
        if(flag)    printf("No Answer\n");
        else        printf("%lld\n", ans);
    }

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Guugle/p/12047592.html