zoukankan      html  css  js  c++  java
  • 【BZOJ1880】[SDOI2009]Elaxia的路线 (最短路+拓扑排序)

    [SDOI2009]Elaxia的路线

    题目描述

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

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

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

    输入输出格式

    输入格式:

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

    第二行:四个整数(x1、y1、x2、y2(1 ≤ x1 ≤ N,1 ≤ y1 ≤ N,1 ≤ x2 ≤ N,1 ≤ y2 ≤ N)),分别表示(Elaxia)的宿舍和实验室及w**的宿舍和实验室的标号(两对点分别 (x1,y1)(x2,y2))。

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

    输出格式:

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

    输入输出样例

    输入样例#1:

    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
    

    输出样例#1:

    3
    

    说明

    对于(30\%)的数据,(N ≤ 100)

    对于(60\%)的数据,(N ≤ 1000)

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

    题解

    大致题意:给定2个起点和终点,求它们最短路的最长公共路径长度。

    标题说的拓扑排序是正解,我发现枚举很简单,就先写了枚举,回头填坑。。。

    我们可以跑(4)(Dij),处理出(s1,t1,s2,t2)的单源最短路(dist1,dist2,dist3,dist4)数组。

    然后(N^2)枚举两个端点,若

    ​ $dist1[i]+dist2[i]dist1[t1] &&dist3[i]+dist4[i]dist3[t2] $

     且$dist1[j]+dist2[j]dist1[t1]&&dist3[j]+dist4[j]dist3[t2] $

    (i,j)在一条最短路上,(ans=max(ans,abs(dist1[i]-dist1[j])));

    这样原数据是可以通过的,但实际上有一个问题,所以被hack了。

    就是我们枚举的(i,j)可能符合上述条件,但并不在一条最短路上,而是在两条分开的最短路上。

    学长告诉我只需要拿个pd数组判一下就可以了。太懒了没有改,所以下面是没有改正的代码。

    code:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #define ll long long
    #define R register
    #define M 2000000
    #define N 2000
    #define INF 0x3f3f3f3f
    using namespace std;
    template<typename T>inline void read(T &a){
        char c=getchar();T x=0,f=1;
        while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
        a=f*x;
    }
    int n,m,h[N],tot,dist1[N],dist2[N],dist3[N],dist4[N];
    int vis[N],s1,s2,t1,t2,ans;
    struct node{
        int nex,to,dis,ord; 
    }edge[M<<1]; 
    inline void add(R int u,R int v,R int w){
        edge[++tot].nex=h[u];
        edge[tot].to=v;
        edge[tot].dis=w;
        h[u]=tot;
    }
    struct HeapNode{
        int u,d;
        friend bool operator < (const HeapNode &a,const HeapNode &b){
            return a.d>b.d;
        }
    };
    priority_queue<HeapNode> q;
    inline void dij(R int s,R int dist[]){
        for(R int i=1;i<=n;i++)dist[i]=INF,vis[i]=0;
        q.push((HeapNode){s,0});dist[s]=0;
        while(!q.empty()){
            R int x=q.top().u;q.pop();
            if(vis[x])continue;vis[x]=1;
            for(R int i=h[x];i;i=edge[i].nex){
                R int xx=edge[i].to;
                if(dist[xx]>dist[x]+edge[i].dis){
                    dist[xx]=dist[x]+edge[i].dis;
                    q.push((HeapNode){xx,dist[xx]});
                }
            }
        }
    }
    int main(){
        read(n);read(m);
        read(s1);read(t1);read(s2);read(t2);
        for(R int i=1,u,v,w;i<=m;i++){
            read(u);read(v);read(w);
            add(u,v,w);add(v,u,w);
        }
        dij(s1,dist1);dij(t1,dist2);
        dij(s2,dist3);dij(t2,dist4);
        for(R int i=1;i<=n;i++){
            if(dist1[i]+dist2[i]!=dist1[t1]||dist3[i]+dist4[i]!=dist3[t2])continue;
            for(R int j=1;j<=n;j++){
                if(dist1[j]+dist2[j]!=dist1[t1]||dist3[j]+dist4[j]!=dist3[t2])continue;
                ans=max(ans,abs(dist1[i]-dist1[j]));
            }
        }
        else printf("%d
    ",ans);
        return 0;
    }
    

    我争取及时填坑,并学习正解-->拓扑排序。。。。

  • 相关阅读:
    Linux 文件查询
    Linux 文件与目录的权限
    Linux查看文件内容
    Linux文件与目录管理
    Linux的文件权限
    java 源码编译
    jvm 字节码执行 (二)动态类型支持与基于栈的字节码解释执行
    jvm 字节码执行 (一)方法调用
    玩转mongodb(七):索引,速度的引领(全文索引、地理空间索引)
    玩转mongodb(六):索引,速度的引领(普通索引篇)
  • 原文地址:https://www.cnblogs.com/ZAGER/p/9833223.html
Copyright © 2011-2022 走看看