解题思路
考虑要计算来回,就从起点分别两遍SPFA,一遍原图,一遍反图(把所有边反向)。计算两遍的和就好了
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#define ll long long
#define ldb long double
using namespace std;
int n,m,X,k1,k2,ans;
int head1[100010],head2[100010],x[100010],y[100010],w[100010],f1[100010],f2[100010],v[100010];
struct c{
int x,next,w;
}a[100010];
struct cc{
int x,next,w;
}b[100010];
void add1(int x,int y,int w)
{
a[++k1].x=y;
a[k1].next=head1[x];
a[k1].w=w;
head1[x]=k1;
}
void add2(int x,int y,int w)
{
b[++k2].x=y;
b[k2].next=head2[x];
b[k2].w=w;
head2[x]=k2;
}
void SPFA1(){
queue<int>q;
memset(f1,0x7f,sizeof(f1));
q.push(X);
v[X]=1;
f1[X]=0;
while(!q.empty())
{
int nx=q.front();
q.pop();
for(int i=head1[nx];i;i=a[i].next)
{
int y=a[i].x;
if(f1[y]>f1[nx]+a[i].w)
{
f1[y]=f1[nx]+a[i].w;
if(!v[y])
{
v[y]=1;
q.push(y);
}
}
}
v[nx]=0;
}
}
void SPFA2(){
queue<int>q;
memset(f2,0x7f,sizeof(f2));
memset(v,0,sizeof(v));
q.push(X);
v[X]=1;
f2[X]=0;
while(!q.empty())
{
int nx=q.front();
q.pop();
for(int i=head2[nx];i;i=b[i].next)
{
int y=b[i].x;
if(f2[y]>f2[nx]+b[i].w)
{
f2[y]=f2[nx]+b[i].w;
if(!v[y])
{
v[y]=1;
q.push(y);
}
}
}
v[nx]=0;
}
}
int main(){
scanf("%d%d%d",&n,&m,&X);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x[i],&y[i],&w[i]);
add1(x[i],y[i],w[i]);
add2(y[i],x[i],w[i]);
}
SPFA1();
SPFA2();
for(int i=1;i<=n;i++)
ans=max(ans,f1[i]+f2[i]);
printf("%d",ans);
}