zoukankan      html  css  js  c++  java
  • 洛谷P2149 Elaxia的路线

    传送门啦

    分析:

    我最开始想的是跑两遍最短路,然后记录一下最短路走了哪些边(如果有两条最短路就选经过边多的),打上标记。两边之后找两次都标记的边有多少就行了。

    但。。。我并没有实现出来。

    最后让我们看一下正解:

    四边spfa+拓扑排序求最长边

    先让我们考虑如何求两对点最短路的最长公共路径?

    1.先明白:如果有一条边,它的起点到最短路的起点 + 终点到最短路的终点 + 边权 == 最短路起点到终点的距离,那么这条边一定在最短路上。

    也就是说如果有一条边i:from -> to权值是w在最短路x -> y上,那么有disx->from + disto->y + edge[i].w == disx->y

    2.所以就可以把两条最短路径都经过的边重新建图

    3.最后就是求最长路即可(显然图是DAG 拓扑排序可以求)。

    注意!!注意!!注意!!

    1.最开始我们建的是无向图,也就是说:dis_{from->to} + wdisfrom>to+w 和 dis_{to->from} + wdisto>from+w是一样的。

    2.重新建图的时候我们建的是有向图。

    最短路和普通的spfaspfa没什么区别,稍微改了一下dis数组,那样就不用开4个dis了。

    拓扑序也差不多,ind[i]ind[i]表示第ii点的入度。

    总体来说,这个题主要还是想法,还有对基础算法的应用。挺好一个题。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int maxn = 1505;
    
    inline int read(){
        char ch = getchar(); int f = 1 , x = 0;
        while(ch > '9' || ch < '0'){if(ch == '-') f = -1; ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = (x << 3) + (x << 1) + ch - '0'; ch = getchar();}
        return x * f;
    }
    
    int n,m,x,y,xx,yy,u,v,w;
    struct Edge{
        int from,to,next,val;
        int tag;
    }edge[maxn * maxn] , e[maxn * maxn];
    int head1[maxn],tot1,head2[maxn],tot2;
    int dis[5][maxn],ind[maxn];
    bool vis[maxn];
    int f[maxn];
    
    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){
        queue<int> q;
        for(int i=1;i<=n;i++)  dis[flag][i] = 1e9;
        memset(vis,false,sizeof(vis));
        q.push(s);
        dis[flag][s] = 0;  vis[s] = true;
        while(!q.empty()){
            int cur = q.front();
            q.pop(); vis[cur] = false;
            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){
                    dis[flag][v] = dis[flag][cur] + edge[i].val;
                    if(vis[v] == 0){
                        q.push(v);
                        vis[v] = true;
                    }
                }
            }
        }
    }
    
    inline void topo(){
        queue<int> que;
        que.push(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);
                }
            }
        }
    }
    
    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]++;
            }
        }
    }
    
    int main(){
        n = read(); m = read();
        x = read(); y = read(); xx = read(); yy = read();
        for(int i=1;i<=m;i++){
            u = read(); v = read(); w = read();
            add(u , v , w);
            add(v , u , w);
        }
        spfa(x , 1);
        spfa(y , 2);
        spfa(xx , 3);
        spfa(yy , 4);
        rebuild();
        topo();
        printf("%d
    ",f[y]);
        return 0;
    }
    顺风不浪,逆风不怂。
  • 相关阅读:
    列表的创建02
    python如何设置注释模板,文件模板
    python语言使用rsa密码算法对数据加密时不能对中文加密问题的解决
    python编码解码,字符数据转换问题(自学笔记)
    字符串与数组之间的互相转换
    vc++文本编辑
    OCP 062【中文】考试题库(cuug内部资料)第28题
    OCP 062【中文】考试题库(cuug内部资料)第27题
    OCP 062【中文】考试题库(cuug内部资料)第26题
    OCP 062【中文】考试题库(cuug内部资料)第25题
  • 原文地址:https://www.cnblogs.com/Stephen-F/p/9864749.html
Copyright © 2011-2022 走看看