POJ 3013 SPFA

来源:互联网 发布:tv版软件 编辑:程序博客网 时间:2024/05/22 11:51

原著:http://blog.163.com/no_reason/blog/static/2000292572011111841550180/

题目:

Description

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 throughn. 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 numbersv,e (0 ≤v, e ≤ 50000) are given in the first line of each test case. On the next line,v positive integerswi indicating the weights ofv nodes are given in one line. On the followinge lines, each line contain three positive integersa,b,c indicating the edge which is able to connect two nodesa andb, and unit price c.

All numbers in input are less than 216.

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.

 

题目大意:这道题说的是找一棵树,但使得造价最小,这棵树的总造价=每条边的造价之和,而边的造价=它所有子节点造价之和*边的单位造价。

解题思路:这道题考的就是最短路劲的问题,因为根节点已经固定,所以只需计算出1号节点到所有节点的最短路劲即可。但是图中会存在环,所以用SPFA算法比较好。但是题目中提到了“No Answer”的情况,这情况就是有独立的节点,及没有任何边与之相接。

代码:

#include<iostream>#include<algorithm>#include<queue>#include<stdio.h>using namespace std;#define N 50005//weight记录节点的权值,head记录每个节点第一条边的的位置int weight[N],head[N];//mark,标记节点是否入队bool mark[N];//dis,存储根节点到其他节点的距离long long dis[N];//边struct node{ int t,c,next;}edge[N*2];int tot;//增加边,void add(int f,int t,int c){edge[tot].t=t;edge[tot].c=c; edge[tot].next=head[f];//记录上条边的位置head[f]=tot++; //记录本条边的位置edge[tot].t=f;edge[tot].c=c; edge[tot].next=head[t]; head[t]=tot++;}//求最短路劲void spfa(int n){int i,to,k; queue<int> q; //初始化dis和markfor(i=1;i<=n;i++)dis[i]=-1,mark[i]=0; dis[1]=0;mark[1]=1;q.push(1);while(!q.empty()){  k=q.front(); q.pop(); mark[k]=0;//节点出对标记为0for(i=head[k];i!=-1;i=edge[i].next){  to=edge[i].t;  //能松弛就松弛if(dis[to]==-1||dis[to]>dis[k]+edge[i].c){    dis[to]=dis[k]+edge[i].c;   if(!mark[to]){     mark[to]=1; //节点入队标记为1  q.push(to);   }  }  }}}int main(){ int cas,n,m; int i,j;scanf("%d",&cas);while(cas--){  scanf("%d %d",&n,&m); for(i=1;i<=n;i++) scanf("%d",&weight[i]);  tot=0;  memset(head,-1,sizeof(head));for(i=1;i<=m;i++){   int f,t,c;  scanf("%d %d %d",&f,&t,&c); add(f,t,c); } spfa(n);long long ans=0; int flag=1;  for(i=1;i<=n;i++){ ans+=dis[i]*weight[i];//计算花费if(dis[i]==-1)//如果存在dis[i]==-1,说明有节点时独立的{  flag=0; break;  } } if(!flag){  printf("No Answer\n");}  else printf("%I64d\n",ans); } return 0;}



 

原创粉丝点击