首先,自已先用数组模拟邻接链表,以前使用模版的,现在可以不看模版自己写了。。。
边的信息:
struct EDGE
{
int u;//起点
int v;//终点
lint len;//边的长度
int next;
}edge[MAX*3+1];//一定要边的范围
int head [MAX];//头节点
void init()//初始化信息,-1;
{
for(int i=1;i<=n;i++)
head[i]=-1;
k=1;
}
插入边
void insert(int u,int v,__int64 len)
{
edge[k].v=v; edge[k].len=len; edge[k].next=head[u];head[u]=k;k++;//正边
edge[k].v=u; edge[k].len=len; edge[k].next=head[v];head[v]=k;k++;//反边
}
遍历:for(int i=head[top];i!=-1;i=edge[i].next)
然后看题意:
有一些点,每个点都有一个重量值,然后给出了一些边,每个边都有一个权值最后让用一些边组成一棵树,使得花费最少,每个边(u,v)的花费=(边得所有子孙节点的重量和)*(该边的权值)对于这个花费,可以看出,对于每条边(u,v),其花费就相当于每个在后面的结点都走了这个边一次,那么我们可以假想,已经形成了最优的树,观察这颗树,就能发现,对于一条边(u,v),由于边的子女都走了这条边一次,而且是在一棵树中,那么从根结点到边的某个子女结点的路径必然包含(u,v),其他边同理,那么所有边的花费之和,就可以转化为(从根结点到某个结点的路径长度*结点重量)之和 那么之后就是求最短路径了。
注意:某些地方会超过int,所以开long long 就好了,INF的值也设的大一些。比如100亿,因为最短路径的极限数据应该是50000*2^16>2^31
代码:
#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
using namespace std;
const int MAX=50001;
typedef unsigned long long lint;
const long long INF=999999999;
struct EDGE
{
int u;
int v;
lint len;
int next;
}edge[MAX*3+1];
int head [MAX];
lint weight[MAX];
lint dist[MAX];
bool vis[MAX];
lint n;
int k=1;
void init()
{
for(int i=1;i<=n;i++)
head[i]=-1;
k=1;
}
void insert(int u,int v,__int64 len)
{
edge[k].v=v; edge[k].len=len; edge[k].next=head[u];head[u]=k;k++;
edge[k].v=u; edge[k].len=len; edge[k].next=head[v];head[v]=k;k++;
}
void spfa(int s)
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
dist[i]=INF;
dist[s]=0;
queue<int>qu;
qu.push(s);
while(!qu.empty())
{
int top=qu.front();
qu.pop();
vis[top]=0;
for(int i=head[top];i!=-1;i=edge[i].next)
{
if(dist[edge[i].v]>dist[top]+edge[i].len)
{
dist[edge[i].v]=dist[top]+edge[i].len;
if(!vis[edge[i].v])
{
vis[edge[i].v]=1;
qu.push(edge[i].v);
}
}
}
}
}
int main()
{
int cas;
scanf("%d",&cas);
while(cas--)
{
lint m;
scanf("%I64d%I64d",&n,&m);
init();
for(int i=1;i<=n;i++)
scanf("%I64d",&weight[i]);
int u,v;
lint c;
for(int i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
scanf("%I64d",&c);
insert(u,v,c);
}
spfa(1);
int flag=1;
lint sum=0;
for(int i=1;i<=n;i++)
{
if(dist[i]==INF)
{
flag=0;break;
}
sum+=weight[i]*dist[i];
}
if(flag)
printf("%d\n",sum);
else
printf("No Answer\n");
}
return 0;
}