这题第一感觉就是Floyd:方便快捷,也很直接。sum+=d[1][i]+d[i][1] (i---- 1->n);
但显然悲剧超时,然后就想到Floyd的优化算法Spfa。一般的都会用上队列,比如vector确实好用,但这题太坑,卡vector超时,然后听取了其他人的想法用邻接表解决了。
#include<stdio.h>
#define MAXN 1000010
#define MOD 1000007
#define inf 10000000000000LL
typedef long long ll;
struct etype
{
int to;
int w;
int next;
}e[MAXN],re_e[MAXN];
int list1[MAXN],list2[MAXN];
ll min1[MAXN],min2[MAXN];
int q[MOD]; //相当于队列
bool inq[MAXN];
void spfa(int n,int s,int *list,etype * edge,ll *min)
{
for (int i=1;i<=n;i++)
min[i]=inf,inq[i]=0;
min[s]=0,inq[s]=1,q[0]=s;
int beg=0,end=1;
while(beg!=end) //就像是!q.empty()
{
int t=q[beg];
beg=(beg+1)%MOD;
for (int p=list[t];p!=-1;p=edge[p].next) //其实这里用了邻接表和数组代替队列感觉就像是Dijkstra的思想了
{
int j=edge[p].to,w=edge[p].w;
if (min[j]>min[t]+w)
{
min[j]=min[t]+w;
if (!inq[j])
inq[j]=1,q[end]=j,end=(end+1)%MOD;
}
}
}
}
int main()
{
int test;
scanf("%d",&test);
while(test--)
{
int n,m;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
list1[i]=-1,list2[i]=-1;
for (int i=0;i<m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
e[i].to=b,e[i].w=c,e[i].next=list1[a],list1[a]=i; // 注意这个邻接表list[i]实际上就是q[a].push_back(b);最后配合next实现,而它是后往前,vector是前往后
re_e[i].to=a,re_e[i].w=c,re_e[i].next=list2[b],list2[b]=i; //实际上就是把图反过来 求学生回来的情况,大家可以画图模拟一下
}
spfa(n,1,list1,e,min1);
spfa(n,1,list2,re_e,min2);
ll ans=0;
for (int i=1;i<=n;i++)
ans+=(min1[i]+min2[i]);
printf("%I64d\n",ans);
}
return 0;
}