思路

通过求出dis的交集来得到公共路径。然后重新建一个图。
对x1,y1,x2,y2分别进行一次求最短路,交集部分(点的dis相同)进行rebuild,生成一个可拓扑排序求最长路径的DAG.
因为做了课件,代码的注释写得很详细,这里就不细讲了。

题解

#include <bits/stdc++.h>

using namespace std;

const int maxn = 1505;
const int maxm =1505*1505;

struct Edge{
    int from,to,next,val;
    int tag; //对边进行标记 
}edge[maxn * maxn], e[maxn * maxn];//第一次建图和第二次建图 
int n, m, x, y, xx, yy, u, v, w;
bool vis[maxn]; //用来跑最短路 
int dis[5][maxn], ind[maxn], f[maxn]; 
//dis[i][j]表示i类型(是谁的起点或终点)为起点,j结点的最短距离
//ind[i]表示i的入度
//f[i]表示在新建图中的最长路径 

int head1[maxn], tot1,head2[maxn], tot2;
//两张图的链式前向星建边 
void add(int u, int v, int w)  //用于第一次建图 
{
    edge[++tot1].to = v;
    edge[tot1].from = u;
    edge[tot1].next = head1[u];
    edge[tot1].val = w;
    head1[u] = tot1;
}

void addedge(int u, int v, int w) //用于第二次建图 
{
    e[++tot2].from = u;
    e[tot2].to = v;
    e[tot2].val = w;
    e[tot2].next = head2[u];
    head2[u] = tot2;
}

void spfa(int s,int flag) //使用spfa求最短路 
{
    queue<int> q;
    for(int i=1 ;i<=n; i++)
    {
        dis[flag][i] = 1e9; //初始化最短路 
        vis[i]=0; //注意要刷新vis数组 
    }
    q.push(s);
    dis[flag][s] = 0;
    vis[s] = 1;
    while(!q.empty())
    {
        int cur = q.front();
        q.pop();
        vis[cur] = 0;
        for(int i=head1[cur]; i; i=edge[i].next)
        {
            int v = edge[i].to;
            if(dis[flag][v] > dis[flag][cur] + edge[i].val)
            {  //flag表示从哪里为起点 
                dis[flag][v] = dis[flag][cur] + edge[i].val;
                if(vis[v] == 0){
                    q.push(v);
                    vis[v] = 1;
                }
            }
        }
    }
}

void topo() //拓扑排序求最长路 
{
    queue<int> que;
    que.push(x); //默认以x为起点 
    while(!que.empty())
    {
        int cur = que.front();
        que.pop();
        for(int i=head2[cur]; i; i=e[i].next)
        {
            int v = e[i].to , w = e[i].val;
            ind[v]--;
            if(!ind[v]) 
            {
                que.push(v);
                f[v] = max(f[v] , f[cur] + e[i].tag * w); //对f进行转移 
            }
        }
    }
}

void rebuild()
{ //对于最短路跑过的边,进行重建图 
    for(int i=1;i<=tot1;i++)
    {
        int v = edge[i].to , u = edge[i].from , w = edge[i].val;
        if(dis[1][u] + w + dis[2][v] == dis[1][y]) //表示最短路经过了这条边 
        {
            addedge(u , v , w);
            if(dis[3][u] + w + dis[4][v] == dis[3][yy] || dis[3][v] + w + dis[4][u] == dis[3][yy])
            //为了处理无向图的问题 
            e[tot2].tag = 1; //对当前边进行标记 
            ind[v]++;   //这条边能走了,那么边的终端点入度+1 
        }
    }
}

int main() //主函数部分 
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    cin>>x>>y>>xx>>yy;
    for(int i=1;i<=m;i++)
    {
        cin>>u>>v>>w;
        add(u , v , w);
        add(v , u , w);
    }
    spfa(x , 1); //对于两人的起点终点都跑一遍最短路 
    spfa(y , 2);
    spfa(xx , 3);
    spfa(yy , 4);
    rebuild();
    topo();
    printf("%d\n",f[y]); //输出到达y的路径长度即可 
    return 0;
}