http://poj.org/problem?id=3013
题意上是子孙节点的权值和乘边重。怎么看都觉得很怪。
所以要看成每个节点到1(根)的最短路径乘上该点的权值。
这么看就是最短路了。
有点类似于去计算每个点的贡献,而不是计算每个边的贡献。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf 10000000000000
using namespace std;
struct node{
int v;
long long cost;
int nex;
};
node eg[111111];
int head[55555];
int ss[555555];
long long we[55555];
int e;
void insert(int st,int ed,long long cost)
{
eg[e].v=ed;
eg[e].cost=cost;
eg[e].nex=head[st];
head[st]=e;
e++;
}
long long dis[55555];
bool vis[55555];
void spfa(int st)
{
memset(vis,0,sizeof(vis));
dis[st]=0;
int l=0;
int r=1;
ss[l]=st;
vis[st]=1;
int t;
while(l<r)
{
t=ss[l];
l++;
vis[t]=0;
for(int i=head[t];i!=-1;i=eg[i].nex)
{
if(dis[eg[i].v]>dis[t]+eg[i].cost)
{
dis[eg[i].v]=dis[t]+eg[i].cost;
if(vis[eg[i].v]==0)
{
ss[r++]=eg[i].v;
vis[eg[i].v]=1;
}
}
}
}
}
int main(){
int t;
cin>>t;
int n,m;
while(t--)
{
cin>>n>>m;
e=0;
for(int i=0;i<=n;i++)
dis[i]=inf;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
{
scanf("%lld",&we[i]);
}
int u,v;
long long cost;
for(int i=1;i<=m;i++)
{
scanf("%d%d%lld",&u,&v,&cost);
insert(u,v,cost);
insert(v,u,cost);
}
if(n<=1)
{
cout<<"0"<<endl;
continue;
}
spfa(1);
long long ans=0;
int f=1;
for(int i=1;i<=n;i++)
{
if(dis[i]==inf)
{
f=0;
break;
}
ans+=we[i]*dis[i];
}
if(f==1)
cout<<ans<<endl;
else {
cout<<"No Answer"<<endl;
}
}
return 0;
}