看似不是单源点最短路的,单源点最短路。其实这个题目说让你求出这些边的价值,刚开始误以为是最小生成树,挺像的,但是边的权值你不好算。因为每条边的权值= (sum of weights of all descendant nodes) × (unit price of the edge),然后脑子里面yy出一张图,其实你算每个节点的价值,算出然后求和就是这个题目要求的。然后单源点最短路径就出现了,直接套用spfa模板,然后就水过了。呵呵。
#include<iostream>
#include<queue>
#include<cstring>
#include<stdio.h>
using namespace std;
struct edge{
long long start;
long long end;
long long len;
long long next;
};
long long tot;
long long list[50010];
edge D[100010];
long long dist[50010];
bool vis[50010];
long long weight[50010];
void add(long long a,long long b,long long c)
{
tot=tot+1;
D[tot].start=a;
D[tot].end=b;
D[tot].len=c;
D[tot].next=list[a];
list[a]=tot;
}
void spfa()
{
long long i;
queue<long long> qu;
long long now=1;
memset(vis,false,sizeof(vis));
memset(dist,-1,sizeof(dist));
vis[now]=true;
dist[now]=0;
qu.push(now);
while(!qu.empty())
{
now=qu.front();
qu.pop();
vis[now]=false;
for(i=list[now];i!=-1;i=D[i].next)
{
long long temp;
temp=dist[now]+D[i].len;
if(temp<dist[D[i].end]||dist[D[i].end]==-1)
{
dist[D[i].end]=temp;
if(vis[D[i].end]==false)
{
vis[D[i].end]=true;
qu.push(D[i].end);
}
}
}
}
}
int main()
{
long long T,sum,i,m,n,a,b,c,flag;
cin>>T;
while(T--)
{
memset(list,-1,sizeof(list));
sum=0;
flag=0;
tot=0;
cin>>n>>m;
for(i=1;i<=n;i++)
scanf("%lld",&weight[i]);
for(i=1;i<=m;i++)
{
scanf("%lld%lld%lld",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
spfa();
for(i=2;i<=n;i++)
{
if(dist[i]==-1)
{
flag=1;
break;
}
sum=sum+weight[i]*dist[i];
}
if(flag==1)
cout<<"No Answer"<<endl;
else cout<<sum<<endl;
}
return 0;
}