题意:
重点理解:price of an edge will be (sum of weights of all descendant nodes) × (unit price of the edge);看似求类似最小生成树的题,其实仔细想想可以转换成最短路的问题;
即:给你一幅无向图,求root点到每个点的最短距离(dis[i])*每个点的权值(W[i])的和;price of an edge will be (sum of weights of all descendant nodes) × (unit price of the edge)
源代码:
/*SPFA*/
/*
思路:
ans=root到每个结点的最短距离(dis[i])*每个点的权值(W[i])的和
注意点:
(1):无向图
(2):用__int64
*/
/*AC代码:672ms*/
#include <iostream>
#include <cstdio>
#include <memory.h>
#include <queue>
#include <algorithm>
#define MAXN 50005
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define INF 1e18
using namespace std;
struct edge
{
int u,v,next;
__int64 w;
}E[2*MAXN];
int head[MAXN],ecnt;
__int64 W[MAXN];
__int64 dis[MAXN];
bool vis[MAXN];
int N,M;
void Insert(int u,int v,__int64 w)
{
E[ecnt].u=u;
E[ecnt].v=v;
E[ecnt].w=w;
E[ecnt].next=head[u];
head[u]=ecnt++;
}
void Init()
{
int i,u,v;
__int64 w;
memset(head,-1,sizeof(head));ecnt=0;
scanf("%d%d",&N,&M);
for(i=1;i<=N;i++)
scanf("%I64d",&W[i]);
for(i=1;i<=M;i++)
{
scanf("%d%d%I64d",&u,&v,&w);
Insert(u,v,w);
Insert(v,u,w);
}
}
queue<int>Q;
void SPFA()
{
int i,u,v;
__int64 w;
while(!Q.empty()) Q.pop();
memset(vis,false,sizeof(vis));
for(i=1;i<=N;i++)
dis[i]=INF;
dis[1]=0;
vis[1]=true;
Q.push(1);
while(!Q.empty())
{
u=Q.front();Q.pop();
vis[u]=false;
for(i=head[u];i!=-1;i=E[i].next)
{
v=E[i].v;w=E[i].w;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(!vis[v])
{
vis[v]=true;
Q.push(v);
}
}
}
}
}
void Solve()
{
int i;
SPFA();
__int64 ans=0;
bool ok=true;
for(i=1;i<=N;i++)
{
if(dis[i]==INF)
{ok=false;break;}
ans+=dis[i]*W[i];
}
if(!ok)
printf("No Answer\n");
else
printf("%I64d\n",ans);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
Init();
Solve();
}
return 0;
}