1 条题解

  • 0
    @ 2026-6-17 1:55:07

    // 最短路图+拓扑排序 Dijkstra 算法 O(MlogN)
    #include<bits/stdc++.h>
    #define pii pair<int,int>
    using namespace std;
    
    const int N=1505,M=6e5+5;
    int idx,h[N],to[M],ww[M],ne[M];
    void add(int u,int v,int w){
      to[++idx]=v,ww[idx]=w,ne[idx]=h[u],h[u]=idx;
    }
    int n,m,s1,t1,s2,t2;
    int d[4][N];
    
    void dijkstra(int s,int k){
      memset(d[k],0x3f,sizeof d[k]); d[k][s]=0;
      priority_queue<pii,vector<pii>,greater<pii> > q;
      q.emplace(0,s);
      while(!q.empty()){
        auto [dd,u]=q.top(); q.pop();
        if(dd!=d[k][u]) continue;
        for(int i=h[u];i;i=ne[i]){
          int v=to[i],w=ww[i];
          if(d[k][v]>d[k][u]+w){
            d[k][v]=d[k][u]+w;
            q.emplace(d[k][v],v);
          }
        }
      }
    }
    
    int on[M],rd[N],f[N],g[N],ans;
    void topo(){
      queue<int> q; q.push(s1); //对甲的DAG图做拓扑排序
      while(!q.empty()){
        int u=q.front(); q.pop();
        ans=max({ans,f[u],g[u]});
        for(int i=h[u]; i; i=ne[i])if(on[i]){ //如果边i是甲的DAG中的边
          int v=to[i],w=ww[i];                //如果(u,v)也是乙的DAG中的边,那么累计长度
          if(d[2][u]+w+d[3][v]==d[2][t2]) f[v]=max(f[v],f[u]+w); //同向走
          if(d[3][u]+w+d[2][v]==d[2][t2]) g[v]=max(g[v],g[u]+w); //反向走
          if(--rd[v]==0) q.push(v);
        }
      }
    }
    int main(){
      scanf("%d%d%d%d%d%d",&n,&m,&s1,&t1,&s2,&t2);
      for(int i=1,u,v,w;i<=m;i++) scanf("%d%d%d",&u,&v,&w),add(u,v,w),add(v,u,w);
      
      dijkstra(s1,0),dijkstra(t1,1);
      dijkstra(s2,2),dijkstra(t2,3); //预处理以4个点为起点的最短路
      
      for(int u=1;u<=n;u++)for(int i=h[u];i;i=ne[i]){
        int v=to[i],w=ww[i];
        if(d[0][u]+w+d[1][v]==d[0][t1]) on[i]=1,rd[v]++; //标记甲的DAG图上的边和点的入度
      }
      topo();
      printf("%d",ans);
    }
    
    • 1

    D97 最短路径图+拓扑排序 Dijkstra 算法[SDOI2009] Elaxia的路线

    信息

    ID
    3545
    时间
    1000ms
    内存
    125MiB
    难度
    10
    标签
    递交数
    3
    已通过
    2
    上传者