[Sdoi2009]Elaxia的路线

Posted wolfycz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Sdoi2009]Elaxia的路线相关的知识,希望对你有一定的参考价值。

Description
最近,Elaxia和w(**)的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间。Elaxia和w(**)每天都要奔波于宿舍和实验室之间,他们 希望在节约时间的前提下,一起走的时间尽可能的长。 现在已知的是Elaxia和w(**)所在的宿舍和实验室的编号以及学校的地图:地图上有N个路 口,M条路,经过每条路都需要一定的时间。 具体地说,就是要求无向图中,两对点间最短路的最长公共路径。

Input
第一行:两个整数N和M(含义如题目描述)。 第二行:四个整数x1、y1、x2、y2(1 ≤ x1 ≤ N,1 ≤ y1 ≤ N,1 ≤ x2 ≤ N,1 ≤ ≤ N),分别表示Elaxia的宿舍和实验室及w(**)的宿舍和实验室的标号(两对点分别 x1,y1和x2,y2)。 接下来M行:每行三个整数,u、v、l(1 ≤ u ≤ N,1 ≤ v ≤ N,1 ≤ l ≤ 10000),表 u和v之间有一条路,经过这条路所需要的时间为l。

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

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

直接上4遍SPFA,然后找到同为两条最短路上的边,进行拓扑排序,找到最大值。做完之后记得将某条路径的起点和终点交换再做一次

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read(){
    int x=0,f=1;char ch=getchar();
    for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())    x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}
inline void print(int x){
    if (x>=10)  print(x/10);
    putchar(x%10+'0');
}
const int N=1.5e3,M=5e5;
struct S1{
    int pre[(M<<1)+10],now[N+10],child[(M<<1)+10],val[(M<<1)+10],tot;
    S1(){tot=0;memset(now,0,sizeof(now));}
    void init(){tot=0,memset(now,0,sizeof(now));}
    void join(int x,int y,int z){pre[++tot]=now[x],now[x]=tot,child[tot]=y,val[tot]=z;}
    void insert(int x,int y,int z){join(x,y,z),join(y,x,z);}
}Old,New;
struct S2{
    int dis[N+10];
    S2(){memset(dis,63,sizeof(dis));}
}Frw_1,Frw_2,Bck_1,Bck_2;
int h[N+10],F[N+10],deg[N+10];
int Ans,Dis_1,Dis_2,n,m;
bool vis[N+10];
void SPFA(int x,int *dis){
    int head=0,tail=1;
    h[1]=x,dis[x]=0,vis[x]=1;
    while (head!=tail){
        if (++head>N)   head=1;
        int Now=h[head];
        for (int p=Old.now[Now],son=Old.child[p];p;p=Old.pre[p],son=Old.child[p]){
            if (dis[son]>dis[Now]+Old.val[p]){
                dis[son]=dis[Now]+Old.val[p];
                if (!vis[son]){
                    if (++tail>N)   tail=1;
                    vis[h[tail]=son]=1;
                }
            }
        }
        vis[Now]=0;
    }
}
bool check_1(int x,int y,int v){return Frw_1.dis[x]+v+Bck_1.dis[y]==Dis_1;}
bool check_2(int x,int y,int v){return Frw_2.dis[x]+v+Bck_2.dis[y]==Dis_2;}
void Get_Ans(int S_1,int T_1,int S_2,int T_2){
    New.init();
    memset(F,0,sizeof(F));
    memset(deg,0,sizeof(deg));
    for (int x=1;x<=n;x++)
        for (int p=Old.now[x],son=Old.child[p];p;p=Old.pre[p],son=Old.child[p])
            if (check_1(x,son,Old.val[p])&&check_2(x,son,Old.val[p]))
                New.join(x,son,Old.val[p]),deg[son]++;
    int head=1,tail=0;
    for (int i=1;i<=n;i++)  if (!deg[i])    h[++tail]=i;
    for (;head<=tail;head++){
        int Now=h[head];
        for (int p=New.now[Now],son=New.child[p];p;p=New.pre[p],son=New.child[p]){
            F[son]=max(F[son],F[Now]+New.val[p]);
            if (!(--deg[son]))  h[++tail]=son;
        }
    }
    for (int i=1;i<=n;i++)  Ans=max(Ans,F[i]);
}
int main(){
    n=read(),m=read();
    int S_1=read(),T_1=read(),S_2=read(),T_2=read();
    for (int i=1;i<=m;i++){
        int x=read(),y=read(),z=read();
        Old.insert(x,y,z);
    }
    SPFA(S_1,Frw_1.dis);
    SPFA(S_2,Frw_2.dis);
    SPFA(T_1,Bck_1.dis);
    SPFA(T_2,Bck_2.dis);
    Dis_1=Frw_1.dis[T_1];
    Dis_2=Frw_2.dis[T_2];
    Get_Ans(S_1,T_1,S_2,T_2);
    swap(Frw_1,Bck_1);
    Get_Ans(T_1,S_1,S_2,T_2);
    printf("%d
",Ans);
    return 0;
}

以上是关于[Sdoi2009]Elaxia的路线的主要内容,如果未能解决你的问题,请参考以下文章

洛谷——P2149 [SDOI2009]Elaxia的路线

[SDOI2009]Elaxia的路线

[Sdoi2009]Elaxia的路线

[SDOI2009]Elaxia的路线

BZOJ 1880: [Sdoi2009]Elaxia的路线

bzoj 1880 [Sdoi2009]Elaxia的路线(最短路+拓扑序)