///这个题目有点意思,搞了很久过了的样例,后来发现全部都白做了,一直RE RE ,一首fuck送给题目;
///说说这个题目吧,就是求1节点到所给任意节点的最短路径之和ans1,再求任意除1节点外的节点到1节点(反向)的最短距离之和ans2;ans=ans1+ans2;
///那为什么我发现全白做了呢,因为我用的是dijkstra,它们给我的节点的个数是1e6,瞬间就傻逼了;
///那么这个题就好做多了,无意间发现前向星是一个好东西,说白了就是数组对领接表的一个优化;所以加上SPFA就可以求两次的最短路了(前向闪现,反向开大);
///核心:SPFA+领接表的优化;(土鳖邻接矩阵版本肯定是不能做的)
///这个是我第一个领接表的写法,所以这个得好好的详细的解说一下了;
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e6+7;
int head[maxn],n,m;
long long dis[maxn];
struct node
{
int to,w,next;///分别表示:终点,权值,最重要的形成表的一个东西,就是当前节点与下一条边的储存位置(箭头指向上一个节点就OK了);
}eage[maxn];
void Add(int top,int u,int v,int w)
{
eage[top].to=v;
eage[top].w=w;
eage[top].next=head[u];
head[u]=top;
///-1<-0<-1<-2;类似于形成一个这样的东西,再遍历的时候只需要判断i是不是-1就完美了(后来慢慢的看着就像是领接数组);
}
long long SPFA()
{
memset(dis,inf,sizeof(dis));
queue<int>Q;
Q.push(1);
dis[1]=0;
while(!Q.empty())
{
int u=Q.front();
Q.pop();
for(int i=head[u];i!=-1;i=eage[i].next)
{
int v=eage[i].to;
if(dis[v]>dis[u]+eage[i].w)
{
dis[v]=dis[u]+eage[i].w;
Q.push(v);
}
} ·
}
long long ans=0;
for(int i=1;i<=n;i++)
ans+=dis[i];///记录两次最短路之和;
return ans;
}
int main ()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m);
memset(head,-1,sizeof(head));///一般来说,head的初始值都赋值为-1;
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&a1[i],&a2[i],&a3[i]);
Add(i,a1[i],a2[i],a3[i]);///先顺着建立领接表。
}
long long ans=SPFA();
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++)
Add(i,a2[i],a1[i],a3[i]);///再次建表,反向得到每个节点到1节点的最短距离;
ans+=SPFA();
printf("%lld\n",ans);
}
return 0;
}
POJ-1511(SPFA找最短路(正向和反向))
最新推荐文章于 2022-02-17 13:15:00 发布