zoukankan      html  css  js  c++  java
  • P3831 [SHOI2012]回家的路 (分层图最短路)

    题目链接

    将每个点拆分乘两个点,一个是横向的,一个是纵向的,如果这个点是站点,那么,对于这个点的横向和纵向之间连一条边权为 1 的边,然后,对于横向之间进行连边, 对于纵向之间进行连边, 但如果每个点都这样的话, 内存肯定是要炸的。 可以知道,这个题中,对我们有用的就只有各个站点和起点终点。
    所以,我们要排序

    #include <bits/stdc++.h>
    const int maxn = 200050;
    const int maxm = 10000050; //边数,往大的开
    const int inf = 0x3f3f3f3f;
    using namespace std;
    typedef long long ll;
    
    struct point{
        int x, y;
        int xu;
    }p[maxn];
    int b[maxn], c[maxn];
    bool cmpx(int qian, int hou){       //按x排序
        if(p[qian].x == p[hou].x)   //x相等  y也要排个序
            return p[qian].y < p[hou].y;
        return p[qian].x < p[hou].x;
    }
    bool cmpy(int qian, int hou){       //按y排序
        if (p[qian].y == p[hou].y)   //y相等  x也要排个序
            return p[qian].x < p[hou].x;
        return p[qian].y < p[hou].y;
    }
    int n, m, s, t;
    //1~m  横向    m+1~2m 纵向
    struct note{
        int to, w;
        int next;
    } e[maxm];
    int head[maxn], cnt;
    void add(int u, int v, int w){
        cnt++;
        e[cnt].to = v, e[cnt].w = w;
        e[cnt].next = head[u], head[u] = cnt;
    }
    struct node{
        int pos, dis;
        node(){}
        node(int pos1, int dis1) { pos = pos1, dis = dis1; }
        bool operator<(const node& qian)const{
            return qian.dis < dis;
        }
    };
    bool vis[maxn];
    int dis[maxn];
    
    void DJ(){
        for (int i = 1; i <= 2 * m; i++)
            dis[i] = inf;
        dis[s] = 0;
        priority_queue<node> q;
        q.push(node(s, 0));
        while(!q.empty()){
            node temp = q.top();
            q.pop();
            int u = temp.pos;
            if(vis[u])
                continue;
            vis[u] = true;
            for (int i = head[u]; i; i=e[i].next){
                int v = e[i].to, w = e[i].w;
                if(dis[v] > dis[u] + w){
                    dis[v] = dis[u] + w;
                    if(!vis[v])
                        q.push(node(v, dis[v]));
                }
            }
        }
        if(dis[t] == inf)
            dis[t] = -1;
        printf("%d
    ", dis[t]);
    }
    
    int main()
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= m; i++){
            scanf("%d%d", &p[i].x, &p[i].y);
            p[i].xu = i;
            b[i] = c[i] = i;
        }
        int x1, y1, x2, y2;
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        p[++m].x = x1, p[m].y = y1, p[m].xu = m, b[m] = c[m] = m, s = m; //将起点添加进去
        p[++m].x = x2, p[m].y = y2, p[m].xu = m, b[m] = c[m] = m, t = m; //将终点添加进去
        sort(b + 1, b + m + 1, cmpx);   //映射排序
        sort(c + 1, c + m + 1, cmpy);   //映射排序
        for (int i = 2; i <= m; i++)
        {
            if (p[b[i]].x == p[b[i - 1]].x)
            { //横向之间
                int u = p[b[i]].xu, v = p[b[i - 1]].xu;
                int w = (p[b[i]].y - p[b[i - 1]].y) * 2;    //计算权值
                add(u, v, w), add(v, u, w);
            }
            if (p[c[i]].y == p[c[i - 1]].y)
            { //纵向之间
                int u = p[c[i]].xu + m, v = p[c[i - 1]].xu + m;
                int w = (p[c[i]].x - p[c[i - 1]].x) * 2;    // 计算权值
                add(u, v, w), add(v, u, w);
            }
        }
        for (int i = 1; i <= m - 2; i++)
            add(i, i + m, 1), add(i + m, i, 1); //一个点之间的换乘
        add(s, s + m, 0), add(s + m, s, 0);
        add(t, t + m, 0), add(t + m, t, 0);
        DJ();
        return 0;
    }
    
  • 相关阅读:
    spring MVC fromeWork 與webwork2 mvc 比較
    JAVA Oauth 认证服务器的搭建
    HTTPS的工作原理
    理解HTTP幂等性
    支付交易一般性准则
    设计模式六大原则
    腾讯微信技术总监周颢:一亿用户增长背后的架构秘密
    Valid Parentheses
    4Sum
    Letter Combinations of a Phone Number
  • 原文地址:https://www.cnblogs.com/jizhihong/p/13337342.html
Copyright © 2011-2022 走看看