這道題很不錯,要用最短路,建新圖,拓撲排序。
我一開始想的是求一遍floyd,找出兩個點 u,v,使得 dis[s][u]+dis[u][v]+dis[v][t]=dis[s][t],另一條路線也滿足着一個條件,找到最長的dis[u][v],但超時無疑,我就不會改了。
正解:
對4個點分別求一遍最短路,之後枚舉每一條邊 u-v,若dis1[u]+w+dis2[v]=dis1[t1],則這條邊在最短路上,如果另一條路也滿足這一條件,則這是兩條最短路的公共路線,就把他加入新圖中,最後在新圖中用拓撲排序求一下最長路.
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
inline void getint(int &x){
x=0; int res=1; char c=getchar();
while(!(c>='0'&&c<='9')){ if(c=='-') res=-1; c=getchar(); }
while(c>='0' && c<='9') x=x*10+c-'0', c=getchar();
x*=res;
}
typedef long long LL;
const int N=1510, M=N*N;
const LL INF=100000000000000;
int n, m, mi, m2, x1, y1, x2, y2;
int head[N], h2[N], du[N];
LL s1[N], t1[N], s2[N], t2[N], tmp[N];
bool inq[N], vis[N];
queue <int> Q;
struct Edge{
int to,next,w;
}e[N*N], e2[N*N];
inline void add(int u,int v,int w){
e[++mi] = (Edge){v,head[u],w};
head[u] = mi;
}
inline void add2(int u,int v,int w){
du[v]++;
e2[++m2] = (Edge){v,h2[u],w};
h2[u] = m2;
}
inline void spfa(int s,LL *d){
for(int i=1; i<=n; ++i) d[i]=INF, inq[i]=false;
while(!Q.empty()) Q.pop();
Q.push(s); d[s]=0;
int u, v, p;
while(!Q.empty()){
u=Q.front(); Q.pop(); inq[u]=false;
for(p=head[u]; p; p=e[p].next){
v = e[p].to;
if(d[v]>d[u]+e[p].w){
d[v] = d[u]+e[p].w;
if(!inq[v]){
inq[v] = true;
Q.push(v);
}
}
}
}
}
inline bool check(int u,int v,int w){
return (s1[u]+(LL)w+t1[v]==s1[y1] && s2[u]+(LL)w+t2[v]==s2[y2])||(s1[u]+(LL)w+t1[v]==s1[y1] && s2[v]+(LL)w+t2[u]==s2[y2]);
}
inline LL topo(){
LL ans=0;
while(!Q.empty()) Q.pop();
for(int i=1; i<=n; ++i) if(!du[i] && vis[i]) Q.push(i);
int u, v, p;
while(!Q.empty()){
u=Q.front(); Q.pop();
for(p=h2[u]; p; p=e2[p].next){
v = e2[p].to; tmp[v] = max(tmp[v], tmp[u]+e2[p].w);
if(!(--du[v])){
Q.push(v);
//tmp[v] = max(tmp[v], tmp[u]+e2[p].w);
}
}
}
for(int i=1; i<=n; ++i) ans=max(ans,tmp[i]);
return ans;
}
int main(){
scanf("%d%d%d%d%d%d",&n,&m,&x1,&y1,&x2,&y2);
for(int i=1, u, v, w; i<=m; ++i){
getint(u); getint(v); getint(w);
add(u,v,w); add(v,u,w);
}
spfa(x1,s1); spfa(y1,t1); spfa(x2,s2); spfa(y2,t2);
for(int u=1, p, v; u<=n; ++u){
for(p=head[u]; p; p=e[p].next){
v = e[p].to;
if(check(u,v,e[p].w)){ vis[u]=vis[v]=true; add2(u,v,e[p].w); }
}
}
printf("%lld\n",topo());
return 0;
}