zoukankan      html  css  js  c++  java
  • 洛谷 P2149 [SDOI2009]Elaxia的路线(两个最短路的公共路径)

    • 题意: 求两对点间最短路的最长公共路径。
    • 思路: 一开始想求出两个最短路的路径,然后暴力求公共路径,发现最短路的路径并不是唯一的。要对s1,t1,s2,t2,求出单源最短路,对于一条边(u,v,w)能够成为s1到t1的最短路上的点,有(d[u][s1] + w + d[v][t1] == d[t1][s1]),即s1到u的距离加上边权和t1到v的距离等于t1到s1的距离.
      先通过这个条件构造出s1到t1的最短路新图,再在这个图上判断是否也为s2到t2的最短路(或t2到s2的最短路),最后在两个条件都满足的边构成的有向图上拓扑排序求最长链即为答案.
    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    typedef  pair<int,int> pii;
    const int N = 2000;
    const int inf = 0x3f3f3f3f;
    struct E{
        int u,v,w,next;
    }edge[N*N*2];
    
    vector<int> path1,path2;
    int head[N],tot,head2[N];
    int d[N][5],in[N],dis[N];
    int n ,m;
    void add(int u,int v,int w){
        edge[++tot] = (E){u,v,w,head[u]};   head[u] = tot;
    }
    void add2(int i){
        edge[++tot] = edge[i];  edge[tot].next = head2[edge[i].u];  head2[edge[i].u] = tot;
    }
    void dijkstra(int s,int t){
        for(int i=1;i<=n;++i)   d[i][t] = inf;
        static priority_queue<pii,vector<pii>,greater<pii> > que;
        d[s][t] = 0;   que.push(pii(0,s));
        while(que.size()){
            pii p = que.top();  que.pop();
            int u = p.second;
            if(d[u][t]<p.first)    continue;   
            for(int i=head[u];i;i=edge[i].next){
                int v = edge[i].v, w = edge[i].w;
                if(d[v][t]>d[u][t]+w){
                    d[v][t] = d[u][t]+w;
                    que.push(pii(d[v][t],v));
                }
            }
        }
    }
    void topo(){
        stack<int> st;
        for(int i=1;i<=n;++i){
            if(in[i]==0)    st.push(i),dis[i] = 0;
        }   
        int u,v;
        while(st.size()){
            u = st.top();   st.pop();
            for(int i=head2[u];i;i=edge[i].next){
                v = edge[i].v;
                in[v]--;
                dis[v] = max(dis[v],dis[u]+edge[i].w);
                if(in[v]==0)    st.push(v);
            }
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        int s1,t1,s2,t2;
        scanf("%d%d%d%d",&s1,&t1,&s2,&t2);
        int u,v,w;
        for(int i=1;i<=m;++i){
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
            add(v,u,w);
        }
        dijkstra(s1,1);
        dijkstra(t1,2);
        dijkstra(s2,3);
        dijkstra(t2,4);
        for(int i=1;i<=n;++i){             
            for(int j=head[i];j;j=edge[j].next){
                if(d[i][1] + edge[j].w + d[edge[j].v][2] == d[t1][1]    // s1 -> t1
                    && d[i][3] + edge[j].w + d[edge[j].v][4] == d[t2][3])// s2 -> t2
                    add2(j),in[edge[j].v]++;
            }
        }
        topo();
        int ans = *max_element(dis+1,dis+1+n);
        memset(head2,0,sizeof head2);
        memset(in,0,sizeof in);
        memset(dis,0,sizeof dis);
        for(int i=1;i<=n;++i){
            for(int j=head[i];j;j=edge[j].next){
                if(d[i][1] + edge[j].w + d[edge[j].v][2] == d[t1][1] // s1 -> t1
                    && d[i][4] + edge[j].w + d[edge[j].v][3] == d[t2][3]) // t2 -> s2 方向相反也算公共路径
                    add2(j),in[edge[j].v]++;
            }
        }
        topo();
        ans = max(ans,*max_element(dis+1,dis+1+n));
        printf("%d
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    (Android)如何将一个高复用性项目供其他项目使用(jar导出,导入,Is Library)(转)
    Android:SlidingMenu 使用详解 .
    单项链表和双向链表的区别
    LinkedList 与 ArrayList的区别
    完全二叉树与满二叉树
    C/C++之回调函数
    C++静态库与动态库
    C++项目中的extern "C" {}
    C++强大背后
    移动优先与响应式Web设计
  • 原文地址:https://www.cnblogs.com/xxrlz/p/11619931.html
Copyright © 2011-2022 走看看