zoukankan      html  css  js  c++  java
  • [BZOJ 4152][AMPPZ 2014]The Captain

    这道题对费用的规定是min(|x1-x2|,|y1-y2|)。如果暴力枚举所有的点复杂度O(n²),n <= 200000,显然爆炸。于是我们要考虑加“有效边”,一个显然的事实是对于两个点,如果经过不在两点连线上的第三个点中转得到的费用之和一定比直接连边小。所以考虑排个序,分别按照x、y排序,依次加边,有点类似贪心的思想,让每次加边的费用尽可能小,然后跑下dijkstra就行。注意,本题卡SPFA。

    P.S 我之前WA了好几次的原因是inf不够大QAQ,每个点坐标<=1e9,inf开1e10才行。或者memset(dis,127,sizeof(dis));

    SPFA死了!!!

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    #define N 200010
    #define M 800010
    #include<iostream>
    #define inf 1e10
    using namespace std;
    struct dij
    {
        int u,dis;
        bool operator < (const dij &a) const
        {
            return dis > a.dis;
        }
    };
    struct point
    {
        int x,y,id;
    }p[N];
    int head[N],nxt[M],to[M],val[M],dis[N];
    int n,cnt;
    void add(int u,int v,int w)
    {
        cnt++;
        nxt[cnt] = head[u];
        head[u] = cnt;
        val[cnt] = w;
        to[cnt] = v;
    }
    bool vis[N];
    void dijkstra(int s)
    {
        memset(dis,127,sizeof(dis));
        dis[s] = 0;
        priority_queue<dij>q;
        dij top,qwq;
        top.u = s;
        top.dis = 0;
        q.push(top);
        while(q.size())
        {
            top = q.top();
            q.pop();
            int u = top.u;
            if(vis[u]) continue;
            vis[u] = 1;
            for(int i = head[u];i;i = nxt[i])
            {
                int v = to[i];
                if(u == v) continue;
                if(dis[v] > dis[u] + val[i])
                {
                    dis[v] = dis[u] + val[i];
                    qwq.u = v;
                    qwq.dis = dis[v];
                    q.push(qwq);
                }
            }
        }
        return;
    }
    bool cmp1(point a,point b)
    {
        if(a.x == b.x) return a.y > b.y;
        return a.x > b.x;
    }
    bool cmp2(point a,point b)
    {
        if(a.y == b.y) return a.x > b.x;
        return a.y > b.y;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i = 1;i <= n;i++)
        {
            scanf("%d %d",&p[i].x,&p[i].y);
            p[i].id = i;//排序后编号会变,用id存下每个点之前的编号
        }
        sort(p + 1,p + 1 + n,cmp1);
        for(int i = 1;i < n;i++)
        {
            add(p[i].id,p[i + 1].id,p[i].x - p[i + 1].x);
            add(p[i + 1].id,p[i].id,p[i].x - p[i + 1].x);
        }
        sort(p + 1,p + 1 + n,cmp2);
        for(int i = 1;i < n;i++)
        {
            add(p[i].id,p[i + 1].id,p[i].y - p[i + 1].y);
            add(p[i + 1].id,p[i].id,p[i].y - p[i + 1].y);
        }
        dijkstra(1);
        printf("%d
    ",dis[n]);
    }
  • 相关阅读:
    v-model
    CSS background 属性
    渐变背景
    mint ui的field用法和修改样式的方法
    js 数组包含
    password 密码查询
    web 单一平台登录逻辑
    内存共享锁业务逻辑(原创)
    无限分类树操作
    根据日期获取,x岁x月x天
  • 原文地址:https://www.cnblogs.com/lijilai-oi/p/10731759.html
Copyright © 2011-2022 走看看