POJ 3013

//算法实现:Dijkstra+邻接表+优先级队列
//解题思路:由于是构造一棵树,则最终所求答案ans = ∑dist[i] * weight[i].(1 <= i <= vn),其中dist[i]为结点i到根结点root(1)的距离,vn为结点数,
//而且weight[i]是固定的,ans仅仅与dist[i]有关。这样就转换成了求各点到根结点的最短路径。
#include <iostream>
#include <algorithm>
#include <queue>
#include <climits>             //引入<climits>的类,注意如果引入<limits>会出现编译错误
#include <cstdio>
//#include <conio.h>
using namespace std;
typedef unsigned long long u64_T;    //类型定义                                                 
const int MAXN = 50001;
const u64_T INF=(u64_T)(1)<<63;  //这种方法比较常用
//const u64_T INF = ULLONG_MAX;    //定义unsigned long long 的最大值
struct edge_T {
     int v;
     u64_T w;
     edge_T *next;
}*adj[MAXN], edges[2*MAXN];     //adj[i]存储以i为起点的邻接表的指针,memo[]存储所有的边
struct node_T {              //用于优先级队列中记录节点的标号和最短路径
     int v;
     u64_T len;
     bool operator < (const node_T &nod) const { //重载优先级队列的操作符,使其从小到大排列(注意格式必须完全一致)
          return len > nod.len;
     }
};
int edgenum;              //记录边的总数
u64_T weight[MAXN];
bool final[MAXN];      //Dijkstra算法中记录该节点是否找到了最短路,为true代表已经找到了最短路径
int vn,en;             //记录定点数和边数
void addEdge(int u, int v, u64_T w) {   
     edge_T *ptr = &edges[edgenum ++];
     ptr -> v = v;
     ptr -> w = w;
     ptr -> next = adj[u];    //往前插入边
     adj[u] = ptr;
}
u64_T dijkstra(int s) {             //n代表结点总数
     priority_queue <node_T> Q;            //使用优先级队列实现
     node_T cur;
     cur.v = s;
     cur.len = 0;
     Q.push(cur);
     u64_T dist[MAXN];                     //存储结点的最小距离 
     for(int i = 1; i <= vn; i ++) dist[i] = INF;       //除源点以外的所有点的距离设置成无穷大(此处与邻接阵实现不同,临界阵赋值为到源点的距离,这里也可但是麻烦
     dist[s] = 0;
     final[s] = true;
     while(! Q.empty()) {
          int v = Q.top().v;               //优先级队列使用top()
          u64_T len = Q.top().len;
          Q.pop();
          final[v]=true;
          for(edge_T *ptr = adj[v]; ptr; ptr = ptr -> next) {
               int u = ptr -> v;
               u64_T w = ptr -> w;
               if(!final[u] && dist[v] + w < dist[u]) {
                    dist[u] = dist[v] + w;
                    cur.v = u;
                    cur.len = dist[u];
                    Q.push(cur);
               }
          }
     }
     for(int i = 1; i <= vn; i ++) {
          if(dist[i] == INF)
               return INF;
     }
     u64_T minimumCost = 0;
     for(int i = 1; i <= vn; i ++) {
          minimumCost += dist[i] * weight[i];
     }
     return minimumCost;
}
int main() {
     //freopen("1.txt","r",stdin);
     int casn;
     scanf("%d", &casn);
     while(casn --) {
          int i;
          scanf("%d %d", &vn, &en);
          for(i = 1; i <= vn; i ++) {
               //scanf("%I64u", &weight[i]);   //读取unsigned long long的两种方法
               scanf("%llu", &weight[i]);
               adj[i] = NULL;                //初始化邻接表的指针
          }
          edgenum = 0;                       //初始化边数
          int u, v;
          u64_T w;
          for(i = 1; i <= en; i ++) {        //双向边
               //scanf("%d%d%I64u", &u, &v, &w); 两种读取方式皆可
               scanf("%d%d%llu", &u, &v, &w);
               addEdge(u, v, w);
               addEdge(v, u, w);
          }
          memset(final,0,sizeof(final));  //初始化
          u64_T minimumCost = dijkstra(1);
          if(minimumCost == INF)
               printf("No Answer\n");
          else
               //printf("%I64u\n", minimumCost);
               printf("%llu\n", minimumCost);
     }
     //getch();
     return(0);
}

posted @ 2010-06-04 18:38  北海小龙  阅读(675)  评论(0编辑  收藏  举报