日常水一波,就是对正向图跑一遍SPFA,然后建一张反向图,也就是求其他所有的节点到源点的距离,然后再跑一遍SPFA。
最后输出两次距离和的最大值就行了。
附上AC代码:
#include <cstdio>
#include <cctype>
#include <queue>
#include <cstring>
#define M 100010
#define N 1010
using namespace std;
struct note{
int to,w,nt;
}z[M*2],f[M*2];
int n,m,st,num,hz[N],hf[N],x,y,w,d1[N],d2[N];
long long ans;
queue <int> que;
bool b[N];
void read(int& a){
static char c=getchar();a=0;int f=1;
while (!isdigit(c)) {if (c=='-') f=-1;c=getchar();}
while (isdigit(c)) a=a*10+c-'0',c=getchar();
a*=f;return;
}
void add(int x,int y,int w){
z[num]=(note){x,w,hz[y]};
f[num]=(note){y,w,hf[x]};
hz[y]=hf[x]=num++;
}
void spfa1(){
while (!que.empty()) que.pop();
memset(b,0,sizeof b);
memset(d1,0x3f,sizeof d1);
que.push(st),d1[st]=0,b[st]=1;
while (!que.empty()){
int p=que.front();que.pop(),b[p]=0;
for (int i=hz[p]; ~i; i=z[i].nt)
if (d1[z[i].to]>d1[p]+z[i].w){
d1[z[i].to]=d1[p]+z[i].w;
if (!b[z[i].to]){
b[z[i].to]=1;
que.push(z[i].to);
}
}
}
return;
}
void spfa2(){
while (!que.empty()) que.pop();
memset(b,0,sizeof b);
memset(d2,0x3f,sizeof d2);
que.push(st),d2[st]=0,b[st]=1;
while (!que.empty()){
int p=que.front();que.pop(),b[p]=0;
for (int i=hf[p]; ~i; i=f[i].nt)
if (d2[f[i].to]>d2[p]+f[i].w){
d2[f[i].to]=d2[p]+f[i].w;
if (!b[f[i].to]){
b[f[i].to]=1;
que.push(f[i].to);
}
}
}
return;
}
int main(void){
read(n),read(m),read(st);
memset(hz,-1,sizeof hz),memset(hf,-1,sizeof hf);
for (int i=1; i<=m; ++i) read(x),read(y),read(w),add(x,y,w);
spfa1(),spfa2();
for (int i=1; i<=n; ++i) ans=max(ans,(long long)d1[i]+d2[i]);
printf("%lld",ans);
return 0;
}