zoukankan      html  css  js  c++  java
  • 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),快去水一发啊!

  • 相关阅读:
    母函数
    匈牙利算法
    AC 自动机
    MFC Invalidate闪屏问题
    求解x=a^b(mod m)
    Millar_rabin和Pollard_Rho
    图论入门算法理解
    Numpy 库常用函数大全
    Linux 系统中“|”管道的作用是什么
    win10 万能修复公式
  • 原文地址:https://www.cnblogs.com/Elfish/p/8066547.html
Copyright © 2011-2022 走看看