题目大意:
从1到N分别给出两点之间的有向图,然后让你求,从一到个点的最短路,以及从个点回到1的最短路之和;
思路:
由于边非常多,采用邻接表并且自己模拟(头插入,用VECTER会超时);
刚开始还想着正向从一开始搜,反向从N开始搜,然而错了!!!反向从N开始搜的是从N到个点的最短路,而不是从个点到1的最短路!!!
所以需要建立一个正向图和一个反向图,均从1开始搜就可以得到结果;
#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1000109;
int n,m,cnt,vis[maxn];
long long ans,d[maxn];
struct node
{
int v,w,next;
}eadge1[maxn],eadge2[maxn];
int head1[maxn],head2[maxn];
void add(node *eadge,int * head,int u,int v,int w)
{
eadge[cnt].v=v;
eadge[cnt].w=w;
eadge[cnt].next=head[u];
head[u]=cnt;
}
void spfa(node *eadge,int * head)
{
memset(vis,0,sizeof vis);
memset(d,inf,sizeof d);
queue<int> q;
q.push(1);
vis[1]=1,d[1]=0;
while(!q.empty())
{
int u=q.front();
q.pop();//由于是求所有点的最短路,所以不用加上if(u==n) break;
vis[u]=0;
for(int i=head[u];i!=-1;i=eadge[i].next)
{
// cout<<"--i="<<i<<endl;
int v=eadge[i].v,c=eadge[i].w;
if(d[v]>d[u]+c)
{
d[v]=d[u]+c;
if(!vis[v])
{
q.push(v);
vis[v]=1;
}
}
}
}
for(int i=2;i<=n;i++)
ans+=d[i];
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(head1,-1,sizeof head1);
memset(head2,-1,sizeof head2);
cnt=0;
scanf("%d%d",&n,&m);
while(m--)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(eadge1,head1,u,v,w);
add(eadge2,head2,v,u,w);
cnt++;
}
ans=0;
spfa(eadge1,head1);spfa(eadge2,head2);
printf("%I64d\n",ans);
}
return 0;
}