哈理工oj(acm.hrbust.edu.cn) 1419【dijkstra + 邻接表 + 堆优化】

 

Description

为了给集训队的训练环境带来点高雅的感觉 ~ 集训队的女队友们决定买些花来作为点缀,可是如果买真花的话会很快枯萎,所以她们决定定制一株假花,它们不会枯萎而且也很漂亮。

每棵假花可以用一些点和边来表示,点表示花朵,边表示枝,点被标记为1n,每棵假花有一个根,规定为1号,每一个点有一个可能不同的造价,每条边也可能不同,所以它们的造价也可能不同,每棵子树定价规定为(所有该子树上的节点的造价和)*(连接该子树与其父节点的边的造价和)。

她们希望这株假花尽可能的大,但又想在保持花的节点数不变的情况下使用尽量小的花费,现在请你来编程帮忙解决这个问题。


Input

输入包含T组,首先给出T的值,每组数据首先给出v,e(0<=v,e<=50000)表示节点数与边数,然后给出一行有v个整数,每个整数wi表示第i个节点的造价,接着是e行,每行有三个整数a,b,c表示a,b节点可以边一条造价为c的边,

所以输入数据不大于2^16

Output

对于每组数据,输入定制这株假花需要的可能最小花费,如果无法制作这株假花,输出“No Answer”。

Sample Input

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

 

Sample Output

15

1210

 

View Code
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int MAXN = 50000 + 10;
typedef long long llong;

struct node
{
    int v, len;
    struct node *next;
};

int nE;
node Edge[MAXN * 2];
node *head[MAXN];

void add_edge(int u, int v, int len)
{
    node *e = Edge + nE++;
    e->v = v;
    e->len = len;
    e->next = head[u];
    head[u] = e;
}

struct Node
{
    int v;
    llong len;
    bool operator < (const Node &B) const {
        return len > B.len;
    }
} vHeap[MAXN];
bool vis[MAXN];

void dijkstra(int n, int s, node *head[], llong len[])
{
    memset(vis, 0, sizeof(vis[0]) * (n+1));
    memset(len, -1, sizeof(len[0]) * (n+1));
    len[s] = 0;
    int cnt = 1;//堆指针。
    vHeap[0].v = s;
    vHeap[0].len = 0;
    for(int i = 0; i < n; i++) {
        int u = -1;//离顶点最短距离的点。
        llong minLen = -1; //最短距离。
        while(cnt > 0) {
            u = vHeap[0].v;
            minLen = vHeap[0].len;
            pop_heap(vHeap, vHeap + cnt); //从新构建堆。
            cnt--;
            if(!vis[u]) {
                break;
            }
            u = -1;
        }
        if(u == -1) {
            break;
        }
        vis[u] = 1;//第一次循环是顶点,因为在循环外面并没有将顶点加入到集合vis里面。
        for(node *e = head[u]; e; e = e->next) {
            if(!vis[e->v] && (len[e->v] == -1 || len[e->v] > minLen + e->len)) {
                len[e->v] = minLen + e->len;//更新最短长度。
                vHeap[cnt].v = e->v;//继续构建堆,所以从cnt开始。
                vHeap[cnt].len = len[e->v];
                cnt++;
                push_heap(vHeap, vHeap+cnt);
            }
        }
    }
}    

int pr_node[MAXN];
llong len[MAXN];

int main()
{
    int i, j;
    int nTest;
    scanf("%d", &nTest);
    while( nTest-- ) {
        int n, e;
        scanf("%d %d", &n, &e);
        for(i = 1; i <= n; i++) {
            scanf("%d", &pr_node[i]);
        }
        nE = 0;
        memset(head, 0, sizeof(head));
        for(i = 0; i < e; i++) {
            int u, v, len;
            scanf("%d %d %d", &u, &v, &len);
            add_edge(u, v, len);
            add_edge(v, u, len);
        }

        dijkstra(n, 1, head, len);
        llong ans = 0;
        for(i = 1; i <= n; i++) {
            if(len[i] < 0) {
                ans = -1;
                break;
            }
            ans += pr_node[i] * len[i];
        }
        if(ans >= 0) {
            printf("%lld\n", ans);
        } else {
            printf("No Answer\n");
        }
    }
    return 0;
}

 

posted @ 2012-07-24 17:07  小猴子、  阅读(1178)  评论(0编辑  收藏  举报