Elaxia的路线题解

求两组最短路的最长公共路径
先跑正图反图,
求出两组的最短路径树,
然后在一组最短路径树上拓扑,
另一棵最短路径树当存在同样的边时更新dp,

#include<bits/stdc++.h>
using namespace std;
const int N=1500;
int n,m,s1,s2,t1,t2,p1,p2,p3,cnt=0,cnt2=0,ans=0,dp[N],rd[N],head[N],head2[N],dis[4][N];
struct edge{int nxt,to,w,v;}e[N*N],f[N*N];
struct xd{
   int z,i;
   bool operator < (const xd &a) const {return z>a.z;}
}tmp,nw;
priority_queue<xd> q;
inline void add(int u,int v,int w){e[++cnt].nxt=head[u],e[cnt].to=v,e[cnt].w=w,head[u]=cnt;}
inline void add2(int u,int v,int w){f[++cnt2].nxt=head2[u],f[cnt2].to=v,f[cnt2].w=w,head2[u]=cnt2,++rd[v];}
inline int read(){
   int T=0,F=1; char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9')  T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T;
}
void dijkstra(int x,int y){
     dis[x][y]=0,tmp.i=y,tmp.z=0,q.push(tmp);
     while(!q.empty()){
        tmp=q.top(),q.pop();
        if(dis[x][tmp.i]<tmp.z) continue;
        for(int i=head[tmp.i];i;i=e[i].nxt){
            nw.i=e[i].to,nw.z=tmp.z+e[i].w;
            if(dis[x][nw.i]>nw.z) dis[x][nw.i]=nw.z,q.push(nw);
        }
     }
}
void tppx(){
     queue<int> qq; int tt; cnt=0;
     for(int i=1;i<=n;++i) if(!rd[i]) qq.push(i);
     while(!qq.empty()){
        tt=qq.front(),qq.pop(),ans=max(dp[tt],ans),head[++cnt]=tt;
        for(int i=head2[tt];i;i=f[i].nxt){
            --rd[f[i].to];
            if(dis[2][tt]+f[i].w+dis[3][f[i].to]==p2) dp[f[i].to]=max(dp[f[i].to],dp[tt]+f[i].w);
            if(!rd[f[i].to]) qq.push(f[i].to);
        }
     }
     memset(dp,0,sizeof(dp));
     for(int i=cnt;i>=1;--i){for(int j=head2[head[i]];j;j=f[j].nxt) if(dis[2][f[j].to]+f[j].w+dis[3][head[i]]==p2) dp[head[i]]=max(dp[head[i]],dp[f[j].to]+f[j].w); ans=max(ans,dp[head[i]]);}
}
int main(){
    n=read(),m=read(),s1=read(),t1=read(),s2=read(),t2=read();
    for(int i=1;i<=m;++i) p1=read(),p2=read(),p3=read(),add(p1,p2,p3),add(p2,p1,p3);
    memset(dis,0x3f,sizeof(dis)),dijkstra(0,s1),dijkstra(1,t1),dijkstra(2,s2),dijkstra(3,t2),p1=dis[0][t1],p2=dis[2][t2];
    for(int j=1;j<=n;++j) for(int i=head[j];i;i=e[i].nxt) if(dis[0][j]+e[i].w+dis[1][e[i].to]==p1) add2(j,e[i].to,e[i].w);
    tppx(),printf("%d\n",ans);
    return 0;
} 
02-01 17:23