zoukankan      html  css  js  c++  java
  • bzoj1880: [Sdoi2009]Elaxia的路线(spfa,拓扑排序最长路)

    1880: [Sdoi2009]Elaxia的路线

    Time Limit: 4 Sec  Memory Limit: 64 MB
    Submit: 1944  Solved: 759
    [Submit][Status][Discuss]

    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,输入数据保证没有重边和自环。

    Source

    Day2

     

     

    /*
    如何求两对点最短路的最长公共路径?
    开始的想法是对两个起点spfa,但对于如何求多条最短路经过的所有点没有思路
    注意到其实本质是求最长路,只是需要一个图...... 
    正解是4遍spfa,若某条边满足起点和终点分别到这条边最短路+这条路长等于起点到终点的最短路
    那么这条边一定在最短路上。
    所以就可以把1,2最短路径都经过的边重建图(注意若某条边不是被同向经过也要算)
    这就有图了...求最长路即可(显然图是DAG  拓扑排序可以求)。 
    */
    #include<bits/stdc++.h>
    
    #define N 2005
    #define M 1000007
    #define inf 0x3f3f3f3f
    
    using namespace std;
    struct node{
        int u,v,w,nxt,f;
    }e[M<<1],E[M<<1];
    queue<int>q;
    int n,m,cnt,cnt2;
    int head[N],p[5],d[5][N],Head[N];
    int in[N],f[N],v[N];
    
    
    void add(int u,int v,int w)
    {
        e[++cnt].u=u;e[cnt].v=v;e[cnt].w=w;
        e[cnt].nxt=head[u]; head[u]=cnt;
    }
    
    void add_(int u,int v,int w)
    {
        E[++cnt2].u=u;E[cnt2].v=v;E[cnt2].w=w;
        E[cnt2].nxt=Head[u]; Head[u]=cnt2;
    }
    
    void spfa(int x)
    {    
        memset(v,0,sizeof v);
        for(int i=1;i<=n;++i) if(i!=p[x]) d[x][i]=inf;
        q.push(p[x]);v[p[x]]=1;
        while(!q.empty())
        {
            int now=q.front();q.pop();v[now]=0;
            for(int i=head[now];i;i=e[i].nxt)
            {
                int to=e[i].v;
                if(d[x][to]>d[x][now]+e[i].w)
                {
                    d[x][to]=d[x][now]+e[i].w;
                    if(!v[to]) v[to]=1,q.push(to);
                } 
            }            
        }
    }
    
    void rebuild()
    {
        for(int i=1;i<=cnt;++i)
        if(d[1][e[i].u]+e[i].w+d[2][e[i].v]==d[1][p[2]])
        {
            add_(e[i].u,e[i].v,e[i].w);
            if(d[3][e[i].u]+e[i].w+d[4][e[i].v]==d[3][p[4]] || d[4][e[i].u]+e[i].w+d[3][e[i].v]==d[3][p[4]]) 
            E[cnt2].f=1;
            in[e[i].v]++;
        }    
    }
    
    void Tsort()
    {
        while(!q.empty()) q.pop();
        q.push(p[1]);
        int now;
        while(!q.empty())
        {
            now=q.front(); q.pop();
            for(int i=Head[now];i;i=E[i].nxt)
            {
                --in[E[i].v];
                if(!in[E[i].v])
                {
                    q.push(E[i].v);
                    f[E[i].v]=max(f[E[i].v],f[now]+E[i].w*E[i].f);
                }
            }
        }
    }
    
    int main()
    {
        int x,y,z;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=4;++i) scanf("%d",&p[i]);
        for(int i=1;i<=m;++i)
        {
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z),add(y,x,z);
        }
        for(int i=1;i<=4;++i) spfa(i);  
        rebuild();
        Tsort();
        printf("%d",f[p[2]]);
        return 0;
    }

     

  • 相关阅读:
    第二节.NET两种交互模式:c/s和b/s
    python自动登录代码
    关于C# webapi ,接口返回字符串和json格式 ,返回值中有反斜杠
    利用java内部静态类实现懒汉式单例
    Linux,Ubuntu,Mint 环境下 navicat 乱码问题
    如何在Linux中使用命令行卸载软件
    Linux安装Oracle JDK替换OpenJDK详解
    【踩坑】利用fastjson反序列化需要默认构造函数
    基于 Markdown 编写接口文档
    Gradle里面两个 依赖管理插件,可以不用关心 具体jar版本号
  • 原文地址:https://www.cnblogs.com/L-Memory/p/9812870.html
Copyright © 2011-2022 走看看