zoukankan      html  css  js  c++  java
  • [SPFA]JZOJ 3086 回家

    Description

    moreD城的城市轨道交通建设终于全部竣工,由于前期规划周密,建成后的轨道交通网络由 2n 条地铁线路构成,组成了一个 纵 横的交通网。如下图所示,这 2n 条线路每条线路都包含 个车站,而每个车站都在一组纵横线路的交汇处。


    出于建设成本的考虑,并非每个车站都能够进行站内换乘,能够进行站内换乘的地铁站共有 个,在下图中,标上方块标记的车站为换乘车站。已知地铁运行 站需要 分钟,而站内换乘需要步行 分钟。 你的最后一个作业就是算出,在不中途出站的前提下,从学校回家最快需要多少时间(等车时间忽略不计)。


     


     

    Input

    第一行有两个整数 n, m。接下去 行每行两个整数 x, y,表示第 条横向线路与第 条纵向线路的交汇站是站内换乘站。接下去一行是四个整数 x1,  y1,  x2,  y2。表示从学校回家时,在第 x1条横向线路与第 y1 条纵向线路的交汇站上车,在第 x2 条横向线路与第 y2 条纵向线路的交汇站下车。


    Output

    仅一个整数表示在合理选择线路的情况下,回家所需要的最少时间。如果无法在不出站换车的情况下回家则输出-1.


     

    Sample Input

    Sample Input 1
    6 9
    2 1
    2 5
    3 2
    4 4
    5 2
    5 6
    6 1
    6 3
    6 4
    1 1 4 6
    
    Sample Input 2
    6 10
    2 1
    2 5
    3 2
    4 4
    5 2
    5 6
    6 1
    6 3
    6 4
    6 6
    1 1 4 6
    
    Sample Input 3
    2 1
    1 2
    1 1 2 2

    Sample Output

    Sample Output 1
    27
    
    Sample Output 2 
    26
    
    Sample Output 3
    5
     

    Data Constraint

     
     

    Hint

    对于10%的数据m=0


    对于 30%的数据,≤ 50, m ≤ 1000


    对于 60%的数据,≤ 500, m ≤ 2000


    对于 100%的数据,≤ 20000, m ≤ 100000

     

    分析

    看到换站要1单位时间就想到了网络流……的建图

    我们把可以换乘的点拆成一条边就行了

    跑SPFA轻松解决

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    using namespace std;
    const int N=2e4+10;
    const int M=1e5+10;
    struct Edge {
        int u,v,w,nx;
    }g[10*M];
    int cnt,list[2*M],d[2*M];
    bool b[2*M];
    struct Point {
        int x,y,id;
    }a[M],s,t;
    int n,m;
    
    bool CMP1(Point a,Point b) {
        return a.x<b.x||a.x==b.x&&a.y<b.y;
    }
    
    bool CMP2(Point a,Point b) {
        return a.y<b.y||a.y==b.y&&a.x<b.x;
    }
    
    void Add(int u,int v,int w) {
        g[++cnt]=(Edge){u,v,w,list[u]};list[u]=cnt;
        g[++cnt]=(Edge){v,u,w,list[v]};list[v]=cnt;
    }
    
    void SPFA(int v0) {
        queue<int> q;
        while (!q.empty()) q.pop();
        for (int i=1;i<=2*m+4;i++) d[i]=2147483647;
        d[v0]=0;b[v0]=1;
        q.push(v0);
        while (!q.empty()) {
            int u=q.front();q.pop();
            for (int i=list[u];i;i=g[i].nx)
                if (d[g[i].v]>d[u]+g[i].w) {
                    d[g[i].v]=d[u]+g[i].w;
                    if (!b[g[i].v]) q.push(g[i].v);
                    b[g[i].v]=1;
                }
            b[u]=0;
        }
    }
    
    int main() {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;i++) scanf("%d%d",&a[i].x,&a[i].y),a[i].id=i,Add(a[i].id,a[i].id+m+2,1);
        scanf("%d%d%d%d",&s.x,&s.y,&t.x,&t.y);s.id=m+1;t.id=m+2;Add(m+1,2*m+3,0);Add(m+2,2*m+4,0);a[m+1]=s;a[m+2]=t;
        sort(a+1,a+m+3,CMP1);
        for (int i=1;i<m+2;i++) if (a[i].x==a[i+1].x) Add(a[i].id,a[i+1].id,2*(a[i+1].y-a[i].y));
        sort(a+1,a+m+3,CMP2);
        for (int i=1;i<m+2;i++) if (a[i].y==a[i+1].y) Add(a[i].id+m+2,a[i+1].id+m+2,2*(a[i+1].x-a[i].x));
        SPFA(m+1);
        printf("%d
    ",d[m+2]==2147483647?-1:d[m+2]);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    在C#程序中模拟发送键盘按键消息
    C# UDPCLIENT多线程实例
    【转】WINFORM下FTP客户端的实现
    抓取屏幕或窗体并保存成图片
    c# 判断窗体已打开则显示为焦点
    【转】C#中dataGridView用法实例分析
    【转】VC6控件小记
    .Net部署二三事之一——如何为VS安装文件MSI制作更新补丁MSP
    [转]C#串口serialPort操作
    VS向IIS发布C#或VB应用程序
  • 原文地址:https://www.cnblogs.com/mastervan/p/10316779.html
Copyright © 2011-2022 走看看