题意:给出n个点,m个边。给出每个点的权值,每个边的权值。求建立一棵树,根节点是1,求这棵树的最小费用,费用=(每条最短路*子树中各顶点的权值)之和。
数组模拟表头,很多需要注意的。加油!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define inf 0xFFFFFFFF //很大40多亿
#define maxn 50005
using namespace std;
class Node
{
public:
int e,v;
int next;
}edge[maxn*2]; //不能忘
int n,m;
int head[maxn];
__int64 dis[maxn]; //数据类型
int visit[maxn];
int weight[maxn];
void spfa()
{
for(int i = 1;i <= n; i++){
dis[i] = inf;
visit[i] = 0;
}
queue<int>Q;
Q.push(1);
visit[1] = true;
dis[1] = 0;
while(!Q.empty()){
int u = Q.front();
Q.pop();
visit[u] = false;
for(int i = head[u];i != -1;i = edge[i].next){
int to = edge[i].e; //注意
if(dis[u] + edge[i].v > dis[to])
continue;
dis[to] = dis[u] + edge[i].v;
if(!visit[to]){
Q.push(to);
visit[to] = true;
}
}
}
}
int main()
{
// freopen("in.txt","r",stdin);
int ncase;
scanf("%d",&ncase);
while(ncase--){
scanf("%d%d",&n,&m);
memset(head,-1,sizeof(head));
for(int i = 1;i <= n; i++)
scanf("%d",&weight[i]);
int a,b,c,pos = 0;
for(int i = 1;i <= m; i++){
scanf("%d%d%d",&a,&b,&c);
edge[pos].v = c;
edge[pos].e = b;
edge[pos].next = head[a]; //注意,这是双向图
head[a] = pos++;
edge[pos].v = c;
edge[pos].e = a;
edge[pos].next = head[b];
head[b] = pos++; //注意
}
spfa();
int flag = false;
long long ans = 0;
for(int i = 1;i <= n; i++){
ans += dis[i]*weight[i];
if(dis[i] == inf){
flag = true;
break;
}
}
if(flag)
printf("No Answer\n");
else
printf("%I64d\n",ans);
}
return 0;
}