这个题目就是一个求最短路,然后保证整个图是一个连通图就好了,如果不连通的就表明了这个圣诞树是无法构成的,那么输出no answer,然后如果是连通的,在求出了所有点到1的最短路径的情况下,利用相乘累加的方式就可以求出答案了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
using namespace std;
typedef long long LL;
const int maxn=500100;
const LL INF=10000000000;
int t,n,e,a,b,c;
LL w[maxn];
struct Edge
{
int v,w,nexts;
}edge[2*maxn];
int head[maxn],cnt;
LL d[maxn];
int counts;
bool vis[maxn];
struct Node
{
int d,u;
bool operator < (const Node& a) const{
return d>a.d;
}
};
void add(int u,int v,int w)
{
Edge p;
p.v=v;
p.w=w;
p.nexts=head[u];
edge[cnt]=p;
head[u]=cnt++;
}
void dijstra(int u)
{
for(int i=1;i<=n;i++) d[i]=INF;
memset(vis,false,sizeof(vis));
d[u]=0;
priority_queue<Node> q;
Node p;
p.d=d[u];
p.u=u;
q.push(p);
while(!q.empty())
{
Node p=q.top();
q.pop();
u=p.u;
if(vis[u]) continue;
vis[u]=1;
for(int k=head[u];k!=-1;k=edge[k].nexts)
{
Edge e=edge[k];
if(!vis[e.v]&&d[e.v]>d[u]+e.w)
{
d[e.v]=d[u]+e.w;
Node p;
p.d=d[e.v];
p.u=e.v;
q.push(p);
}
}
}
return ;
}
int main()
{
scanf("%d",&t);
while(t--)
{
cnt=0;
counts=0;
memset(head,-1,sizeof(head));
memset(vis,false,sizeof(vis));
scanf("%d%d",&n,&e);
for(int i=1;i<=n;i++)
{
scanf("%lld",&w[i]);
}
while(e--)
{
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
if(n==0||n==1)
{
printf("0\n");
continue;
}
dijstra(1);
LL res=0;
int i;
for(i=1;i<=n;i++)
{
if(d[i]==INF)
{
break;
}
res+=d[i]*w[i];
}
if(i==n+1)
{
printf("%lld\n",res);
}
else
{
printf("No Answer\n");
}
}
return 0;
}