对dijkstra的浅见(引例 poj 2457)

非负权值的单源最短路之 dijkstra

Tanky Woo之dijkstra:  http://www.wutianqi.com/?p=1890

dijkstra-------我认为这个算法的核心思想是:最短路径长度递增。其实就是一个贪心算法。

怎么理解呢?

最短路的最优子结构:假如有一条最短路径已经存在了,那么其中任意两点的路径都将是最短的,否则假设是不成立了。

算法实现过程:

  1. 已当前点 pos 更新,dis[ i ]的值(即 点 i 到源点的距离)
  2. 找出dis[ i ] 最小的 i 点,作为当前 pos 点,并且加入集合 S ,
  3. 重复 1 ,2步骤,N次,因为每次都会找出一个点,一共只有N个点;

以poj 2457为例:

Part Acquisition

Description

The cows have been sent on a mission through space to acquire a new milking machine for their barn. They are flying through a cluster of stars containing N (1 <= N <= 50,000) planets, each with a trading post.

The cows have determined which of K (1 <= K <= 1,000) types of objects (numbered 1..K) each planet in the cluster desires, and which products they have to trade. No planet has developed currency, so they work under the barter system: all trades consist of each
party trading exactly one object (presumably of different types).

The cows start from Earth with a canister of high quality hay (item 1), and they desire a new milking machine (item K). Help them find the best way to make a series of trades at the planets in the cluster to get item K. If this task is impossible, output -1.

Input

* Line 1: Two space-separated integers, N and K.

* Lines 2..N+1: Line i+1 contains two space-separated integers, a_i and b_i respectively, that are planet i‘s trading trading products. The planet will give item b_i in order to receive item a_i.

Output

* Line 1: One more than the minimum number of trades to get the milking machine which is item K (or -1 if the cows cannot obtain item K).

* Lines 2..T+1: The ordered list of the objects that the cows possess in the sequence of trades.

Sample Input

6 5
1 3
3 2
2 3
3 1
2 5
5 4

Sample Output

4
1
3
2
5

Hint

OUTPUT DETAILS:

The cows possess 4 objects in total: first they trade object 1 for object 3, then object 3 for object 2, then object 2 for object 5.

题意:物品交换:n个交换方式,k是目标物品,用物品1 换k,求最少交换的次数。

思路:建图 map[u][v]=1,权值为 1,表示一次交换,即每条路都是一种交换方式,由题是单向图。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
#define maxn 1000+10
using namespace std;
int map[maxn][maxn];
int dis[maxn];
int pre[maxn];
int kind;

void dijkstra(int s)
{
    int vis[maxn],minn,pos;
    memset(vis,0,sizeof vis);
    for(int i=0;i<kind+1;i++)
        dis[i]=INF;
    dis[s]=0;
    for(int i=0;i<kind;i++)
    {
        minn=INF;
        for(int j=1;j<=kind;j++)
            if(!vis[j]&&minn>dis[j])
            {
                minn=dis[j];
                pos=j;
            }
        vis[pos]=1;
        for(int j=1;j<=kind;j++)
            if(!vis[j]&&dis[j]>dis[pos]+map[pos][j])
            {
                pre[j]=pos;
                dis[j]=dis[pos]+map[pos][j];                   //每更新一遍dis ,刷新一遍 pre
            }

    }
}

void print_path(int aim)  //路径输出函数
{

    int n=dis[aim];          // dis是多少,就交换了多少次,有多少个前驱。
    int path[maxn];          //倒着记录路径
    int step=0,temp;
    path[++step]=aim;
    temp=aim;
    printf("%d\n",n+1);
    for(int i=0;i<n;i++)
    {
        temp=pre[temp];
        path[++step]=temp;
    }

    for(int i=step;i>=1;i--)  //倒着输出
        printf("%d\n",path[i]);
}

int main()
{
    int n,k;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        int u,v;
        kind=-1;
        for(int i=0;i<maxn;i++)
            for(int j=0;j<maxn;j++)
                map[i][j]=INF;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            map[u][v]=1;
            if(kind<max(u,v))
                kind=max(u,v);
        }
        dijkstra(1);
        if(dis[k]<INF)
            print_path(k);
        else
            printf("-1\n");

    }

    return 0;
}

当然了,这一题还涉及了一个对最短路径的输出问题。

如何输出呢?

设置一个pre [ i ]=pos 数组,记录点 i 的前驱点 pos

为何要设置前驱点呢?

因为dijkstra更新dis【】的时候是根据 pos点更新的,所以每更新一次,就要刷新一遍pre[ ]数组;

即:仅仅只有松弛操作,会对点 v 的前驱点进行改变,所以每进行一遍松弛操作,就要更新前驱结点。





对dijkstra的浅见(引例 poj 2457),布布扣,bubuko.com

时间: 2024-11-09 03:41:09

对dijkstra的浅见(引例 poj 2457)的相关文章

扩展欧几里得算法求解不定方程【例 poj 1061】

扩展欧几里得算法是数论当中一种常用的算法,他可以用如下的姿势来表达: 设a, b为不全为0的整数,则存在整数x和y,使得 gcd(a, b) = a*x + b*y. 证明就略去. 树上还有一个拉梅定理:用欧几里得算法计算两个正整数的最大公因子时,所需要的除法次数不会超过两个整数中较小的那个十进制数的倍数的5倍. 拉梅定理的一个推论:求两个正整数a, b, a > b的最大公因子需要O(log2a)3次的位运算. 至于拉梅定理有什么用,暂时还没有研究=—=. 例1 求225和21的最大公因子s,

POJ 2457 Part Acquisition

第一反应是BFS,比较直观,但是输出路径写的不是很熟练,此外,习惯不好,“==”写成了“=”,所以常量一定放前面! 1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 using namespace std; 5 int N, K; 6 typedef struct node 7 { 8 int in, out; 9 int pos; 10 }Link; 11 const int maxn = 50

递归入门引例

[一]两个最基本的例子 //阶乘 function fac(a:longint):longint; begin if a<2 then fac:=1 else fac:=a*fac(a-1); end; //费波那契数列 function fab(a:longint):longint; begin if a<=2 then fab:=1 else fac:=fab(a-2)+fab(a-1); end; [二]求各位数字之和 输入一个正整数N(0 <= N <= 214748364

java设计模式(1)-------单例,工厂,值对象,装饰模式

      java设计模式(1) 先简单的介绍下设计模式吧:是一种解决问题的一种行之有效的思想:用于解决特定环境下.重复出现的特定问题的解决方案. 那为什么我们需要学习设计模式呢? 1.设计模式都是一些相对优秀的解决方案,很多问题都是典型的.有代表性的问题,学习设计模式,我们就不用自己从头来解决这些问题,相当于在巨人的肩膀上,复用这些方案即可,站的高看到远,就是要站在巨人的肩膀上把他们踩下去,嘿嘿. 2.设计模式已经成为专业人士的常用词汇,不懂不利于交流,能让你变得很牛逼哦. 3.能让你设计的

例谈数学的积累

博文由来 在最近的组卷中,看到这样一个题目[来源于数学难卷],大概思考了其解法过程,颇有感触,作以记录: 案例[高中]若命题\("\exists x\in (0,2]\),不等式\(e^{2x}+e^{-2x}-a(e^x-e^{-x})<0"\)为假命题,则实数\(a\)的取值范围是[] $A.(-\infty,\sqrt{2})$ $B.(-\infty,2\sqrt{2}]$ $C.(0,\sqrt{2}]$ $D.(2\sqrt{2},+\infty)$ 解题过程 分析:

平衡树初阶——AVL平衡二叉查找树+三大平衡树(Treap + Splay + SBT)模板【超详解】

平衡树初阶——AVL平衡二叉查找树 一.什么是二叉树 1. 什么是树. 计算机科学里面的树本质是一个树状图.树首先是一个有向无环图,由根节点指向子结点.但是不严格的说,我们也研究无向树.所谓无向树就是将有向树的所有边看成无向边形成的树状图.树是一种递归的数据结构,所以我们研究树也是按照递归的方式去研究的. 2.什么是二叉树. 我们给出二叉树的递归定义如下: (1)空树是一个二叉树. (2)单个节点是一个二叉树. (3)如果一棵树中,以它的左右子节点为根形成的子树都是二叉树,那么这棵树本身也是二叉

最长上升(不下降)子序列(详细,转)

LIS(Longest Increasing Subsequence)最长上升(不下降)子序列,有两种算法复杂度为O(n*logn)和O(n^2).在上述算法中,若使用朴素的顺序查找在 D1..Dlen查找,由于共有O(n)个元素需要计算,每次计算时的复杂度是O(n),则整个算法的时间复杂度为O(n^2),与原来算法相比没有任何 进步.但是由于D的特点(2),在D中查找时,可以使用二分查找高效地完成,则整个算法时间复杂度下降为O(nlogn),有了非常显著的提高.需要注意 的是,D在算法结束后记

【转载】夜深人静写算法(四)——差分约束

[转载]夜深人静写算法(四) - 差分约束  目录     一.引例       1.一类不等式组的解   二.最短路       1.Dijkstra       2.图的存储       3.链式前向星       4.Dijkstra + 优先队列       5.Bellman-Ford       6.SPFA       7.Floyd-Warshall   三.差分约束        1.数形结合        2.三角不等式        3.解的存在性        4.最大值

差分约束算法总结

来自 https://blog.csdn.net/my_sunshine26/article/details/72849441 差分约束系统 一.概念 如果一个系统由n个变量和m个约束条件组成,形成m个形如ai-aj≤k的不等式(i,j∈[1,n],k为常数),则称其为差分约束系统. 二.引例 给定n个变量和m个不等式,每个不等式的形式为 x[i] - x[j] <= a[k] (0 <= i, j < n, 0 <= k < m, a[k]已知),求 x[i] - x[j]