zoukankan      html  css  js  c++  java
  • [BZOJ1880][Sdoi2009]Elaxia的路线

    题目描述

    最近,(Elaxia)(w)的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间。

    (Elaxia)(w)每天都要奔波于宿舍和实验室之间,他们 希望在节约时间的前提下,一起走的时间尽可能的长。

    现在已知的是(Elaxia)(w)所在的宿舍和实验室的编号以及学校的地图:地图上有(N)个路 口,(M)条路,经过每条路都需要一定的时间。 具体地说,就是要求无向图中,两对点间最短路的最长公共路径。

    Input

    第一行:两个整数(N)(M)(含义如题目描述)。

    第二行:四个整数(x_1,y_1,x_2,y_2(1≤x_1≤N,1≤y_1≤N,1≤x_2≤N,1≤y_2≤N)),分别表示(Elaxia)的宿舍和实验室及(w)的宿舍和实验室的标号(两对点分别 (x_1,y_1)(x_2,y_2))。

    接下来(M)行:每行三个整数,(u),(v),(l)((1≤u≤N,1≤v≤N,1≤l≤10000)),表 (u)(v)之间有一条路,经过这条路所需要的时间为(l)

    对于(30\%)的数据,(N≤100)
    对于(60\%)的数据,(N≤1000)
    对于(100\%)的数据,(N≤1500),输入数据保证没有重边和自环。

    Output

    一行,一个整数,表示每天两人在一起的时间(即最长公共路径的长度)

    Sample Input

    9 10
    1 6 7 8
    1 2 1
    2 5 2
    2 3 3
    3 4 2
    3 9 5
    4 5 3
    4 6 4
    4 7 2
    5 8 1
    7 9 1
    

    Sample Output

    3
    

    很显然,对于在一起的路径,他一定是连续的。

    因为,若不是连续的路径,中间的一段路肯定是走较短的那一段更优。

    所以,那一段路一定是连续的路径。

    问题就变成了,两对点的最短路径的交集的最长链。

    对于一对点的最长链,若满足(dis[x]+cost[x][y]==dis[y]),那么(x->y),这条路径就在最短路图上了。

    求出两个图的交集即可。

    这个图具有拓扑关系,优先级更高的点可以更新其他与他相连的点。

    由此,我们可以找出交集中入度为(0)的点,将其加入源点,同时跑拓扑。

    最后,距离最大的值就是答案了。

    有一个细节就是,题目并没有严格规定方向,所以必须在一对边的最短路图中把反向表也标记。

    代码如下

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <iostream>
    #include <algorithm>
     
    using namespace std;
     
    #define LL long long
    #define u64 unsigned long long
    #define reg register
    #define Raed Read
    #define debug(x) cerr<<#x<<" = "<<x<<endl;
    #define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
    #define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
    #define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
    #define erep(i,G,x) for(reg int i=(G).Head[x]; i; i=(G).Nxt[i])
     
    inline int Read() {
        int res = 0, f = 1;
        char c;
        while (c = getchar(), c < 48 || c > 57)if (c == '-')f = 0;
        do res = (res << 3) + (res << 1) + (c ^ 48);
        while (c = getchar(), c >= 48 && c <= 57);
        return f ? res : -res;
    }
     
    template<class T>inline bool Min(T &a, T const&b) {
        return a > b ? a = b, 1 : 0;
    }
    template<class T>inline bool Max(T &a, T const&b) {
        return a < b ? a = b, 1 : 0;
    }
     
    const int N = 1505, M = N*N, mod = 1e9 + 9;
     
    bool MOP1;
     
    int n,m,sx1,sy1,sx2,sy2;
     
    struct Link_list {
        int Tot,Head[N],Nxt[M],to[M],cost[M];
        inline void AddEdgepair(int a,int b,int c) {
            to[++Tot]=b,cost[Tot]=c,Nxt[Tot]=Head[a],Head[a]=Tot;
            to[++Tot]=a,cost[Tot]=c,Nxt[Tot]=Head[b],Head[b]=Tot;
        }
    } G;
     
    struct T2100 {
        int vis[N],Dis[N],Ans;
        struct node {
            int u,dis;
            bool operator<(node _)const {
                return dis>_.dis;
            }
        };
        void Dij(int x) {
            memset(Dis,6,sizeof Dis);
            memset(vis,0,sizeof vis);
            priority_queue<node>Q;
            Dis[x]=vis[x]=0;
            Q.push((node)<%x,0%>);
            while(!Q.empty()) {
                node Now=Q.top();
                Q.pop();
                int No=Now.u;
                if(vis[No])continue;
                vis[No]=1;
                erep(i,G,No) {
                    int y=G.to[i];
                    if(Dis[No]+G.cost[i]<Dis[y]) {
                        Dis[y]=Dis[No]+G.cost[i];
                        Q.push((node)<%y,Dis[y]%>);
                    }
                }
            }
        }
        int us[N];
        int path1[M];
        bool In1[N];
        bool dfs1(int x) {
            if(x==sy1)return true;
            if(us[x])return In1[x];
            bool tot=false;
            erep(i,G,x) {
                int y=G.to[i];
                if(Dis[x]+G.cost[i]==Dis[y])tot|=(path1[i]=dfs1(y));
            }
            us[x]=1,In1[x]=tot;
            return tot;
        }
        bool In2[N];
        int path2[M],path3[M];
        bool dfs2(int x) {
            if(x==sy2)return true;
            if(us[x])return In2[x];
            bool tot=false;
            erep(i,G,x) {
                int y=G.to[i];
                if(Dis[x]+G.cost[i]==Dis[y])tot|=(path2[i]=path3[i^1]=dfs2(y));
            }
            us[x]=1,In2[x]=tot;
            return tot;
        }
        int In[N];
        void Topu1(void) {
            memset(Dis,0,sizeof Dis);
            queue<int>Q;
            rep(i,1,n)if(!In[i])Q.push((int)i);
            while(!Q.empty()) {
                int x=Q.front();
                Q.pop();
                erep(i,G,x) {
                    int y=G.to[i];
                    if(!path1[i]||!path2[i])continue;
                    if(Dis[x]+G.cost[i]>Dis[y])Dis[y]=Dis[x]+G.cost[i];
                    In[y]--;
                    if(!In[y])Q.push(y);
                }
            }
            rep(i,1,n)Max(Ans,Dis[i]);
        }
        void Topu2(void) {
            memset(Dis,0,sizeof Dis);
            queue<int>Q;
            rep(i,1,n)if(!In[i])Q.push((int)i);
            while(!Q.empty()) {
                int x=Q.front();
                Q.pop();
                erep(i,G,x) {
                    int y=G.to[i];
                    if(!path1[i]||!path3[i])continue;
                    if(Dis[x]+G.cost[i]>Dis[y])Dis[y]=Dis[x]+G.cost[i];
                    In[y]--;
                    if(!In[y])Q.push(y);
                }
            }
            rep(i,1,n)Max(Ans,Dis[i]);
        }
        inline void solve(void) {
            Ans=0;
            Dij(sx1),dfs1(sx1);
            memset(us,0,sizeof us);
            Dij(sx2),dfs2(sx2);
            rep(i,1,n) {
                erep(j,G,i) {
                    int y=G.to[j];
                    if(path1[j]&path2[j])In[y]++;
                }
            }
            Topu1();
            rep(i,1,n) {
                erep(j,G,i) {
                    int y=G.to[j];
                    if(path1[j]&path3[j])In[y]++;
                }
            }
            Topu2();
            printf("%d",Ans);
        }
    } P100;
     
    bool MOP2;
     
    inline void _main(void) {
        n=Raed(),m=Read();
        sx1=Read(),sy1=Read();
        sx2=Read(),sy2=Read();
        G.Tot=1;
        rep(i,1,m) {
            int a=Read(),b=Read(),c=Raed();
            G.AddEdgepair(a,b,c);
        }
        P100.solve();
    }
     
    signed main() {
    #define offline1
    #ifdef offline
        freopen("path.in", "r", stdin);
        freopen("path.out", "w", stdout);
        _main();
        fclose(stdin);
        fclose(stdout);
    #else
        _main();
    #endif
        return 0;
    }
    
  • 相关阅读:
    Hadoop2.x环境搭建
    HDFS序列化
    Hadoop2.x介绍
    eclipse(1)----ubuntu下的安装与配置
    hive与hbase
    mysql----启动报错
    序列化+protobuff+redis
    爬虫学习笔记(2)--创建scrapy项目&&css选择器
    日常随笔
    spark学习(2)--hadoop安装、配置
  • 原文地址:https://www.cnblogs.com/dsjkafdsaf/p/11270289.html
Copyright © 2011-2022 走看看