我们首先知道,答案肯定是最短路图中的某段公共链,那么设(x,y)为x到y的最短路,那么答案为((s1,t1)+(s2,t2)-min((s1,s2)+(t1,t2),(s1,t2),(s2,t1))) div 2,这两种情况分别可以画成下面的图
这样就可以十分明显的看出了。因为中间的一段算了两遍,所以要div 2。
从四个点开始各扫一遍spfa(),vis【】记录是否可以访问。
记录长度相同的最短路上的点都记录下来,再在此简化后的图里进行扫最短路,
由此就可以记录点之间的最短路径,因为每个点都在最短路上,所以上式即可成立。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;
#define ll long long
int s1,s2,t1,t2;
int len[10];
ll b[610000],next[610000],val[610000],p[2000],dis[2000];
ll d1[2000],d2[2000],d3[2000],d4[2000];
bool vis[610000],flag[2000];
int n,e,num;
void build(ll x,ll y,ll z)
{
num++;
b[num]=y;
val[num]=z;
next[num]=p[x];
p[x]=num;
}
void spfa(int st)
{
for(int i=1;i<=n;i++)
{
dis[i]=0x3f3f3f3f;
}
dis[st]=0;
flag[st]=1;
queue<int>q;
q.push(st);
while(!q.empty())
{
int tmp=q.front();
q.pop();
flag[tmp]=0;
int k;
for(k=p[tmp];k;k=next[k])
{
if(dis[b[k]]>dis[tmp]+val[k]&&vis[k])
{
dis[b[k]]=dis[tmp]+val[k];
if(!flag[b[k]])
{
q.push(b[k]);
flag[b[k]]=1;
}
}
}
}
}
ll ans1,ans2,tot1,tot2;
ll ans;
int main()
{
int x,y,z;
num=1;
scanf("%d%d",&n,&e);
scanf("%d%d%d%d",&s1,&t1,&s2,&t2);
for(int i=1;i<=e;i++)
{
scanf("%d%d%d",&x,&y,&z);
build(x,y,z);
build(y,x,z);
}
memset(vis,true,sizeof(vis));
spfa(s1);
ans1=dis[t1];
for(int i=1;i<=n;i++)
d1[i]=dis[i];
spfa(s2);
ans2=dis[t2];
for(int i=1;i<=n;i++)
d2[i]=dis[i];
spfa(t1);
for(int i=1;i<=n;i++)
d3[i]=dis[i];
spfa(t2);
for(int i=1;i<=n;i++)
d4[i]=dis[i];
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
int q=p[i];
for(;q;q=next[q])
{
int k=b[q];
if (d1[i]+val[q]+d3[k]==ans1)
{
vis[q]=true;
vis[q^1]=true;
}
if (d2[i]+val[q]+d4[k]==ans2)
{
vis[q]=true;
vis[q^1]=true;
}
}
}
spfa(s1);
tot1=dis[s2];
tot2=dis[t2];
spfa(t1);
tot1=tot1+dis[t2];
tot2=tot2+dis[s2];;
ans=(ans1+ans2-min(tot1,tot2))/2;
ans=max(ans,(ll)0);
printf("%lld",ans);
return 0;
}