题目让求从起始点到各个路口来回花费的钱之和的最小值是多少,类似于poj3268,正着建个图,再反向建个图,计算两者的最小值之和就可以了;
但是这道题数据比较大,用邻接矩阵会超时也会爆内存,需要用邻接表来建图;要注意题目给的数据过于大,注意类型溢出以及合适的inf值;
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#define N 1000006
const int inf=1e10;//题目数据太大,注意inf的合理取值
int b[N],next[N];
long long dis[N];//注意类型,用int会出现溢出导致WA;
int u[N],v[N],w[N],f[N];
int que[N],head,tail,k,n;
void dij(int next[],int f[],long long dis[],int u[],int v[],int w[])
{
int i;
for(i=1; i<=n; i++)
dis[i]=inf;
dis[1]=0;
memset(b,0,sizeof(b));
memset(que,0,sizeof(que));
head=tail=1;
que[tail]=1;
tail++;
b[1]=1;
while(head<tail)
{
k=f[que[head]];
while(k!=-1)
{
if(dis[v[k]]>dis[u[k]]+w[k])
{
dis[v[k]]=dis[u[k]]+w[k];
if(b[v[k]]==0)
{
que[tail]=v[k];
tail++;
b[v[k]]=1;
}
}
k=next[k];
}
b[que[head]]=0;
head++;
}
}
int main()
{
int m,i,t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
memset(f,-1,sizeof(f));
for(i=1; i<=m; i++)//这里采用数组的形式来实现邻接表,详细介绍可以参照《啊哈,算法》这本书;
{
scanf("%d%d%d",&u[i],&v[i],&w[i]);
next[i]=f[u[i]];
f[u[i]]=i;
}
dij(next,f,dis,u,v,w);//正向建图;
long long sum=0;
for(i=2; i<=n; i++)
sum+=dis[i];
memset(f,-1,sizeof(f));
for(i=1;i<=m;i++)
{
next[i]=f[v[i]];
f[v[i]]=i;
}
dij(next,f,dis,v,u,w);//反向建图;
for(i=2; i<=n; i++)
sum+=dis[i];
printf("%I64d\n",sum);
}
return 0;
}