大体就是SPFA逆向建图,然后通过入出度的关系找出原点和汇点,主要是将关键路径上的点输出,用一个pre数组
记录,所求的最长路上的各个点。且值为上一节点,下标为下一节点。然后将pre数组所描述的路径,通过另一个数组
存下来,输出即可。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<cmath>
#include<math.h>
#include<set>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#define inf 0x3f3f3f3f
#define LL long long
using namespace std ;
int dis[100000],cnt,s,e,head[100010],in[1000000],out[1000000],pre[100000],vex[1000000];
bool vis[100000];
int n;
struct node
{
int v,next,w;
}q[100000];
void bu(int a,int b,int c)
{
q[cnt].v=b;
q[cnt].w=c;
q[cnt].next=head[a];
head[a]=cnt++;
}
void LONG_SPFA()
{
for(int i=0;i<=n;i++)
{
dis[i]=-inf;
}
memset(vis,false,sizeof(vis));
dis[s]=0;
vis[s]=true;
queue<int>Q;
while(!Q.empty())
Q.pop();
Q.push(s);
while(!Q.empty())
{
int x=Q.front();
Q.pop();
for(int i=head[x];~i;i=q[i].next)
{
if( (dis[q[i].v ]<dis[x]+q[i].w)||(dis[q[i].v]==dis[x]+q[i].w&&(x<pre[q[i].v] ) ) )
{
dis[q[i].v ]=dis[x]+q[i].w;
pre[q[i].v ]=x;
if(!vis[q[i].v ])
{
vis[q[i].v ]=true; Q.push(q[i].v);
}
}
}
}
}
int a,b,c;
int main()
{
int m,i,j,k;
while(~scanf("%d%d",&n,&m))
{
cnt=0;
memset(head,-1,sizeof(head));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
memset(vis,false,sizeof(vis));
memset(pre,inf,sizeof(pre));
for(i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
bu(b,a,c);
in[a]++,out[b]++;
}
for(i=1;i<=n;i++)
{
if(!in[i])
s=i;
if(!out[i])
e=i;
}
LONG_SPFA();
printf("%d\n",dis[e]);
int tmp=0;
for(i=e;i!=inf;i=pre[i])
vex[tmp++]=i;
for(i=1;i<tmp;i++)
printf("%d %d\n",vex[i-1],vex[i]);
}
return 0;
}
本文介绍了一种使用SPFA算法逆向构建图的方法来寻找最短路径,并通过节点的出入度确定起点和终点。文章详细展示了如何利用pre数组记录最长路径上的点,并最终输出该路径。
583

被折叠的 条评论
为什么被折叠?



