这个题目的意思是求从1到其他点的最短路径,然后求其他点到0的最短路径。刚开始想的时候觉得可不可以用Floyd做,然后看了一下点数范围到了1000000,太大了。然后这个题还是比较巧妙的,先求从1点开始的单源最短路径。然后用将边反着建一个图,然后再求一次从1点开始的单源最短路径。其实反着建图了,然后1到该点的最短路径就是该点到1的最短路径,其实反着建图了之后,其他点都变为了1,1变为了其他点,所以求其他点到1的距离就可以直接一个单源最短路径就可以求出来了。(不知道我讲清楚了了没有==)
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
#define maxn 1000005
const int INF=0x3f3f3f3f;
struct Edge
{
int to,next;
long long w;
};
struct dl
{
int to;
long long w;
bool operator < (const dl &t)const{
return w>t.w;
}
};
Edge e1[maxn];
Edge e2[maxn];
int head1[maxn];
int head2[maxn];
int vis[maxn];
double dis[maxn];
priority_queue <dl> Q;
int main()
{
int N;
scanf("%d",&N);
while(N--)
{
int n,m;
scanf("%d %d",&n,&m);
memset(head1,-1,sizeof(head1));
memset(head2,-1,sizeof(head2));
memset(e2,0,sizeof(e2));
memset(e1,0,sizeof(e1));
memset(vis,0,sizeof(vis));
for(int i=0;i<m;i++)
{
int from,to;
double w;
scanf("%d %d %lf",&from,&to,&w);
e1[i].to=to;
e1[i].w=w;
e1[i].next=head1[from];
head1[from]=i;
e2[i].to=from;
e2[i].w=w;
e2[i].next=head2[to];
head2[to]=i;
}
while(!Q.empty())
Q.pop();
for(int i=0;i<=n+2;i++)//因为这里dis是double型,然后用memset的话,不会被初始化为INF,会被初始化为一个小数。。
dis[i]=0x3f3f3f3f;
dis[1]=0;
dl k;
k.to=1;
k.w=0;
Q.push(k);
while(!Q.empty())
{
dl t=Q.top();
Q.pop();
if(t.w!=dis[t.to]||vis[t.to])
continue;
vis[t.to]=1;
for(int i=head1[t.to];i>-1;i=e1[i].next)
{
Edge c=e1[i];
if(!vis[c.to]&&dis[c.to]>c.w+t.w)
{
dis[c.to]=c.w+t.w;
Q.push(dl{c.to,dis[c.to]});
}
}
}
long long ans=0;
for(int i=1;i<=n;i++)
ans+=dis[i];
while(!Q.empty())
Q.pop();
for(int i=0;i<=n+2;i++)
dis[i]=0x3f3f3f3f;
memset(vis,0,sizeof(vis));
dis[1]=0;
dl d;
d.to=1;
d.w=0;
Q.push(d);
while(!Q.empty())
{
dl t=Q.top();
Q.pop();
if(t.w!=dis[t.to]||vis[t.to])
continue;
vis[t.to]=1;
for(int i=head2[t.to];i>-1;i=e2[i].next)
{
Edge c=e2[i];
if(!vis[c.to]&&dis[c.to]>c.w+t.w)
{
dis[c.to]=c.w+t.w;
Q.push(dl{c.to,dis[c.to]});
}
}
}
for(int i=1;i<=n;i++)
ans+=dis[i];
cout<<ans<<endl;
}
return 0;
}