bzoj1880 [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 ≤ ≤ N),分别表示Elaxia的宿舍和实验室及w**的宿舍和实验室的标号(两对点分别 x1,y1和x2,y2)。 接下来M行:每行三个整数,u、v、l(1 ≤ u ≤ N,1 ≤ v ≤ N,1 ≤ l ≤ 10000),表 u和v之间有一条路,经过这条路所需要的时间为l。

输出格式:

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

题解

题目已经规定了公共路径在两个对点的最短路上,所以以四个点为起点跑spfa。

遍历一下每条边,如果这条边满足在两对点的最短路上,就把这条边放进新图。容易证明新图是一个没有环的图,所以拓扑排序跑最长链就可以了。

满足一条边在最短路上的条件就是:起点到这个条边的起点的距离+终点到这条边的距离+这条边的长度=起点到终点的最短路

但是其实两个人在公共路径上走的方向不同也可以,所以要反向再做一次

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#define maxn 1510
using namespace std;
struct edge{
    int next,to,w;
}e[maxn*maxn*2];
int cnt,n,m,head[maxn],Head[maxn];
int x1,y1,x2,y2,ans;
int s1[maxn],s2[maxn],t1[maxn],t2[maxn];
int du[maxn];
bool vis[maxn];
void insert(int u,int v,int w){
    cnt++;
    e[cnt].next=head[u];e[cnt].to=v;e[cnt].w=w;
    head[u]=cnt;
}
void Insert(int u,int v,int w){
    cnt++;
    e[cnt].next=Head[u];e[cnt].to=v;e[cnt].w=w;
    Head[u]=cnt;
}
queue<int>q;
void spfa(int x,int dis[]){
        memset(dis,127,sizeof (int)*1510);
        dis[x]=0;q.push(x);
        vis[x]=1;
        while(!q.empty()){
            int now=q.front();q.pop();
            vis[now]=0;
            for(int i=head[now];i;i=e[i].next){
                int s=e[i].to;
                if(dis[s]>dis[now]+e[i].w){
                    dis[s]=dis[now]+e[i].w;
                    if(!vis[s]){
                        vis[s]=1;
                        q.push(s);
                    }
                }
            }
        }
}
inline void topologysort()
{    
    int dis[10000];
    memset(dis,0,sizeof(dis));
    for(int i=1;i<=n;i++)
      if(!du[i]) q.push(i);
    while(!q.empty())
    {
        int tmp=q.front();q.pop();
        ans=max(ans,dis[tmp]);
        for(int i=Head[tmp];i;i=e[i].next)
        {
            dis[e[i].to]=max(dis[e[i].to],dis[tmp]+e[i].w);
            if(!--du[e[i].to]) q.push(e[i].to);
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    int u,v,w;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&u,&v,&w);
        insert(u,v,w);insert(v,u,w);
    }
    spfa(x1,s1);spfa(y1,t1);spfa(x2,s2);spfa(y2,t2);
    for(int tmp=1;tmp<=n;tmp++){
        for(int i=head[tmp];i;i=e[i].next){
            int s=e[i].to;
            if(s1[tmp]+e[i].w+t1[s]==s1[y1]&&s2[tmp]+e[i].w+t2[s]==s2[y2]){
                Insert(tmp,s,e[i].w);
                du[s]++;
            }
        }
    }
    topologysort();
    memset(Head,0,sizeof Head);
    for(int tmp=1;tmp<=n;tmp++){
        for(int i=head[tmp];i;i=e[i].next){
            int s=e[i].to;
            if(s1[tmp]+e[i].w+t1[s]==s1[y1]&&s2[s]+e[i].w+t2[tmp]==s2[y2]){
                Insert(tmp,s,e[i].w);
                du[s]++;
            }
        }
    }
    topologysort();
    printf("%d",ans);
}

不得了啊,那边的洛谷上有一道这个题的重题啊(P2149&P2109),快去水一发啊!

 

posted @ 2017-12-19 16:43  Elfish?  阅读(148)  评论(0编辑  收藏  举报