这道题很不错,要用最短路,建新图,拓扑排序。
我一开始想的是求一遍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;
}