hihocoder 1138 Islands Travel dijkstra+heap 难度:3

很久不用dijkstra,几乎连基本性质也忘了,结果这道题就是考察dijkstra空间复杂度是o(n)

这里总结四种算法

算法名称           时间复杂度       空间复杂度

dijkstra+heap  O(elog(e+n))   O(n)

bellman-ford    O(ne)             O(n)

spfa                O(ke)             O(n)

floyd-warshall   O(n^3)          O(n^2)

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>

using namespace std;
const int maxn = 1e5 + 5;
const int maxm = 1e6 + 6;

int first[maxn],n;
struct edge
{
    int t,c,nxt;
} e[maxm];

void addedge(int f,int t,int c,int ind)
{
    e[ind].nxt = first[f];
    e[ind].t = t;
    e[ind].c = c;
    first[f] = ind;
}

struct pnt
{
    int x,y,id;
    pnt()
    {
        x = y = id = 0;
    }
    pnt(int _x,int _y,int _id)
    {
        x = _x;
        y = _y;
        id = _id;
    }
};
bool cmpx(pnt p1,pnt p2)
{
    if(p1.x!= p2.x)return p1.x < p2.x;
    return p1.y < p2.y;
}
bool cmpy(pnt p1,pnt p2)
{
    if(p1.y!= p2.y)return p1.y < p2.y;
    return p1.x < p2.x;
}
pnt a[maxn];
long long dis[maxn];
bool vis[maxn];
typedef pair<long long ,int> P;
priority_queue<P, vector <P>, greater<P> > que;
long long dijkstra()
{
    for(int i = 0; i < n; i++)dis[i] = 2e18;
    memset(vis,false,sizeof vis);
    while(!que.empty())que.pop();

    dis[0] = 0;
    vis[0] = true;
    for(int p = first[0]; p != -1; p = e[p].nxt)
    {
        int t = e[p].t;
        dis[t] = e[p].c;
        que.push(P(dis[t],t));
    }

    while(!que.empty())
    {
        int f = que.top().second;
        que.pop();
        if(f == n-1)break;
        if(vis[f])continue;
        vis[f] = true;

        for(int p = first[f]; p != -1; p = e[p].nxt)
        {
            int t = e[p].t;
            if(dis[t] > dis[f] + e[p].c){
                dis[t] = dis[f] + e[p].c;
                que.push(P(dis[t],t));
            }
        }
    }

    return dis[n - 1];
}
int main()
{
    while(scanf("%d",&n)==1)
    {
        memset(first, -1, sizeof first);
        for(int i = 0; i < n; i++)
        {
            scanf("%d%d",&a[i].x,&a[i].y);
            a[i].id = i;
        }

        sort(a,a + n,cmpx);
        for(int i = 0; i < n - 1; i++)
        {
            addedge(a[i].id,a[i + 1].id,
                    min(abs(a[i].x - a[i + 1].x),abs(a[i].y - a[i + 1].y)),2 * i);
            addedge(a[i + 1].id,a[i].id,
                    min(abs(a[i].x - a[i + 1].x),abs(a[i].y - a[i + 1].y)),2 * i + 1);
        }
        sort(a,a + n,cmpy);
        for(int i = 0; i < n - 1; i++)
        {
            addedge(a[i].id,a[i + 1].id,
                    min(abs(a[i].x - a[i + 1].x),abs(a[i].y - a[i + 1].y)),2 * i + 2 * n);
            addedge(a[i + 1].id,a[i].id,
                    min(abs(a[i].x - a[i + 1].x),abs(a[i].y - a[i + 1].y)),2 * i + 1 + 2 * n);
        }

        long long ans = dijkstra();
        printf("%lld\n",ans);
    }
    return 0;
}
时间: 2024-07-30 03:23:39

hihocoder 1138 Islands Travel dijkstra+heap 难度:3的相关文章

hihocoder #1138 : Islands Travel

题意,求1到n的最短路.不难想到单源最短路,难点在于数量级太大,因此如何建图是关键: 因为cost = min{|Xi-Xj|, |Yi-Yj|}:所以,点i的移动只有两种情况,1. x距离最近的点,2. y距离最近的点 如此一来,每个点i的最多只有四条边(为什么是四条?),这样复杂度就降下来了,单源最短路的复杂度为n*m(点*边数) 我用spfa. 解题思路: x轴排序,建图 y轴排序,建图 求最短路 用spfa注意队列que的大小至少是n*m,可以使用循环队列 #include <cstdi

Dijkstra + heap

用优先队列实现,和朴素Dijkstra差不多,核心思想没有改变. 模板: struct node { int pos, dist; friend bool operator < (node a, node b) // 定义优先级 { return a.dist > b.dist; // 小的先出 } }; int Dijkstra(int n,int start,int end) // n个点,定义起点和终点 { bool visited[maxn]; int pos; node tmp; t

【CF20C】Dijkstra?(DIJKSTRA+HEAP)

没什么可以说的 做dijk+heap模板吧 以后考试时候看情况选择SFPA和DIJKSTRA 1 const oo=110000000000; 2 var vet,next,len,w:array[1..2100000]of longint; 3 dis:array[1..1100000]of int64; 4 a:array[1..1100000]of int64; 5 b:array[1..1100000]of longint; 6 inq:array[1..1000000]of boole

【BZOJ-1576】安全路径Travel Dijkstra + 并查集

1576: [Usaco2009 Jan]安全路经Travel Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1044  Solved: 363[Submit][Status][Discuss] Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i Output * 第1..N-1行: 第i行包含一个数:从牛棚_1到牛棚_i+1并且避免从牛棚1到牛棚i+1最

【bzoj1576/Usaco2009 Jan】安全路经Travel——dijkstra+并查集

Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i Output * 第1..N-1行: 第i行包含一个数:从牛棚_1到牛棚_i+1并且避免从牛棚1到牛棚i+1最短路经上最后一条牛路的最少的时间.如果这样的路经不存在,输出-1. Sample Input 4 5 1 2 2 1 3 2 3 4 4 3 2 1 2 4 3 输入解释: 跟题中例子相同 Sample Output 3 3 6 输出解释: 跟

Hihocoder #1081 最短路径一 dijkstra

#1081 : 最短路径·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 万圣节的早上,小Hi和小Ho在经历了一个小时的争论后,终于决定了如何度过这样有意义的一天——他们决定去闯鬼屋! 在鬼屋门口排上了若干小时的队伍之后,刚刚进入鬼屋的小Hi和小Ho都颇饥饿,于是他们决定利用进门前领到的地图,找到一条通往终点的最短路径. 鬼屋中一共有N个地点,分别编号为1..N,这N个地点之间互相有一些道路连通,两个地点之间可能有多条道路连通,但是并不存在一条两端都是同一个地点

Dijkstra、Dij + heap、Floyd、SPFA、 SPFA + SLF Template

Dijkstra in Adjacency matrix : int Dijkstra(int src,int tec, int n){ bool done[1005]; int d[1005]; memset(done,0,sizeof(done)); map[0][src] = 0;//巧妙之处,加入超级源点0 for(int i = 0;i <= n;i++) d[i] = (i == src ? 0 : 1000000); for(int i = 0;i <= n;i++){//最多执

hihoCoder 1175:拓扑排序二

题目链接: http://hihocoder.com/problemset/problem/1175 题目难度:一星级(简单题) 今天闲来无事,决定刷一道水题.结果发现这道水题居然把我卡了将近一个钟头. 最后终于调通了.总结起来,原因只有一个:不够仔细. 思路不用细说了,就是拓扑排序的简单应用.然而,一些不起眼的细节才是让你掉坑里的真正原因. 猜猜哪儿可能出bug? // A simple problem, but you can't be too careful with it. #inclu

【BZOJ】1576 [Usaco2009 Jan]安全路经Travel

[算法]最短路树+(树链剖分+线段树)||最短路树+并查集 [题解] 两种方法的思想是一样的,首先题目限制了最短路树唯一. 那么建出最短路树后,就是询问对于每个点断掉父边后重新找路径的最小值,其它路径只能是这个点和其子树节点通过非树边到达非子树节点. 这样考虑很难统计,换个角度考虑每条非树边的影响. 一条非树边连接两个端点u,v,它们会有一个LCA,那么这条非树边就可以影响u~LCA和v~LCA两条链上的点. 这样依然不方便统计,因为两条链上每个点的影响各不相同,所以使用差分的思想. 定义一条非