hdoj1874 (优先队列+Dijkstra)

hdoj1874

分析: 
一看题目, 就是求最短路, 这道题用的是Dijkstra+优先队列。先说一下Dijkstra算法:每次扩展一个距离最短的节点, 更新与其相邻点的距离。 当所有边权都为正时, 由于不会存在一个距离更短的没有扩展的点,所以这个点的距离不会在改变, 保证了算法的正确性。

算法步骤如下: 
G={V,E} 
1. 初始时令 S={V0},T=V-S={其余顶点},T中顶点对应的距离值 
  若存在〈V0,V〉,d(V0,Vi)为〈V0,Vi〉弧上的权值 
  若不存在〈V0,Vi〉,d(V0,Vi)为∞ 
2. 从T中选取一个与S中顶点有关联边且权值最小的顶点W,加入到S中 
3. 对其余T中顶点的距离值进行修改:若加进W作中间顶点,从V0到Vi的距离值缩短,则修改此距离值 
重复上述步骤2、3,直到S中包含所有顶点,即W=Vi为止。

伪代码:

将所有节点状态初始化(标记为未计算) 
设起始点s, d[s] = 0; 其他节点d[i] = MAX; 
循环n次 

  在所有未标记的节点中, 选出d值最小的节点x; 
  标记节点x; 
  对于所有从x节点出发的所有边(x, y), 更新d[y] = min(d[y], d[x] + w(x, y)); 
}

对应代码:

memset(v, 0, sizeof(v));
for(int i = 0; i < n; i++)
    d[i] = 10e8;
d[s] = 0;
for(int i = 1; i < n; i++)
{
    int mi = 10e8;
    for(int j = 1; j < n; j++)
    {
        if(v[j] == 0 && d[j] < mi)
            mi = d[j];
        v[j] = 1;
        for(int k = 0; k < n; k++)
            if(d[k] < d[j] + w[j][k])
                d[k] = d[j] + w[j][k];
    }
}

程序的复杂度为n方, 每一次都要求所有d中的最小值。 然而STL中的优先队列priority_queue正好解决了这一问题。

#include<iostream>
#include<cstdio>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;

int n, m, s, t, v[1005];
double d[1005];
struct edge
{
    int v;
    double d;
}e[1005];
struct node//存储点的信息, 起始点到x节点的最短距离d.
{
    int x;
    double d;
}no[1005];
bool operator< (node a, node b)
{
    return a.d > b.d;
}
vector<edge> vec[1005];
double ac(int x)
{
    memset(v, 0, sizeof(v));
    priority_queue<node> q;
    node tem;
    tem.x = s;
    tem.d = 0;
    q.push(tem);//将起始点加入队列
    while(!q.empty())
    {
        node tem = q.top();//取出d值最小的
        q.pop();
        int x = tem.x;
        if(x == t)
            return tem.d;
        if(v[x] == 1) continue;
        v[x] = 1;
        for(int i = 0; i < vec[x].size(); i++)//更新从tem.x出发的所有边(x,y),d[y] = min(d[y], d[x]+w[x][y])
        {
            int y = vec[x][i].v;
            if(d[y] > (tem.d + vec[x][i].d))
            {
                d[y] = tem.d + vec[x][i].d;
                node node1;
                node1.x = y; node1.d = d[y];
                q.push(node1);
            }
        }
    }
    return -1;
}
int main()
{
    while(scanf("%d%d", &n, &m) != EOF)
    {
        for(int i = 0; i <= n; i++) vec[i].clear();
        for(int i = 0; i <= n; i++) d[i] = 10e8;
        for(int i = 1; i <= m; i++)
        {
            int x, y, w;
            scanf("%d%d%d", &x, &y, &w);
            edge e;
            e.v = y; e.d = w;
            vec[x].push_back(e);//用vector存边,
            e.v = x;
            vec[y].push_back(e);
        }
        scanf("%d%d", &s, &t);
        d[s] = 0;
        double ans = ac(s);
        if(ans == -1)
            printf("-1\n");
        else
            printf("%.0lf\n", ans);
    }
    return 0;
}

时间: 2024-09-19 04:14:38

hdoj1874 (优先队列+Dijkstra)的相关文章

hdu6395 /// 优先队列dijkstra

题目大意: 给定无向图的n m为点数和边数 接下来m行给定u v id表示点u到点v间有一条编号为id的边 当由一条边走到另一条边 而两条边的编号不同时 费用+1 优先队列跑dijkstra最短路 按费用排序 #include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define LL long long #define mem(i,j) memset(i,j,sizeof(i)) #define P pair&

UVA - 658 It’s not a Bug, it’s a Feature!(优先队列Dijkstra)

题目链接 题目大意:补丁和漏洞之间的修复问题.有n种漏洞,m种补丁,接着给你m行代表的是m种补丁使用的情况.前面的n个字符表示的是补丁的使用前提,后面的n个字符表示的是补丁使用完后的漏洞状况.字符'0'代表的是这个漏洞存不存在都没关系,'+'代表的是这个漏洞存在或者出现, '-'代表的是消失或者是不存在.使用每种补丁都需要时间,一开始这些漏洞都是存在的,问最少花多少的时间能够把这些漏洞都消灭. 解题思路:因为有'0'这样的情况,所以需要把不确定的情况暴力的转化为确定的情况,然后用2进制数来表示目

【最短路】Dijkstra+ 链式前向星+ 堆优化(优先队列)

Dijkstra+ 链式前向星+ 优先队列   Dijkstra算法 Dijkstra最短路算法,个人理解其本质就是一种广度优先搜索.先将所有点的最短距离Dis[ ]都刷新成∞(涂成黑色),然后从起点x (Dis[x]= 0, Dis[]值最小 )开始查询:先将x 加入(涂成灰色),对x 的所有边进行遍历,对所有搜索到的点x+ 1 进行松弛(刷新),若经过x 点的松弛,得到的距离小于原来的值:Dis[x]+ dis(x, x+ 1) < Dis[x+ 1], 则用新值刷新,把x+ 1加入(涂成灰

Codevs1041&amp;&amp;Vijos1119 car的旅行路线(最短路dijkstra)

Codevs1041&&Vijos1119  car的旅行路线(最短路) 题目描述 又到暑假了,住在城市A的Car想和朋友一起去城市B旅游.她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t. 那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教.任务找出一条从城市A到B的旅游

HDU-2680 Choose the best route 单向边+反向dijkstra

https://vjudge.net/problem/HDU-2680 题意:给出m条边及其起始点终点与长度,已知可以从w个起点出发,求到某个终点s的最短路径.注意是单向边.m<1e5,w<n<1000. 题解:若每个起点都kijkstra一遍时间复杂度为O((E+VlogV)*V),会TLE,想了一下,终点当初起点,反向建边就可以了 坑点:做图论习题一度因为没看到directed,directional,wa到怀疑dijkstra错了 ac代码,用的邻接表存图及优先队列dijkstr

【beijingwc2012】【BZOJ2662】冻结

Description "我要成为魔法少女!" "那么,以灵魂为代价,你希望得到什么?" "我要将有关魔法和奇迹的一切,封印于卡片之中??" 在这个愿望被实现以后的世界里,人们享受着魔法卡片(SpellCard,又名符 卡)带来的便捷. 现在,不需要立下契约也可以使用魔法了!你还不来试一试? 比如,我们在魔法百科全书(Encyclopedia of Spells)里用"freeze"作为关 键字来查询,会有很多有趣的结果. 例

蓝桥杯练习系统题解

转于:http://www.cnblogs.com/cshhr/p/3550014.html 蓝桥杯官网练习系统题解(非VIP) BEGIN-4(Fibonacci数列) 有递推公式,大家都知道用递推公式求,仅仅要记得在递推的时候同一时候取模求好 这里给一份另类代码,用矩阵高速幂求,事实上还有循环节 /* (1 1) * (Fn-1) = ( Fn )//矩阵相乘,将就着看吧 (1 0) (Fn-2) (Fn-1) (1 1) * (1 1) * (Fn-2) = ( Fn ) (1 0) (1

次短路

Roadblocks Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7921   Accepted: 2896 Description Bessie has moved to a small farm and sometimes enjoys returning to visit one of her best friends. She does not want to get to her old home too q

HDU - 3790 最短路径问题(Dijkstra+优先队列优化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3790 题意:中文题(边被赋予两种属性,一种是路径,一种是花费),然后略.(逃...... 今天看了卿学姐的视频,初尝SPFA和Dijkstra. 一个是用队列优化,一个是用优先队列优化.这道题目用这两种方法都可以. dijkstra算法思想(贪心):从距离起点最近的点开始,从这个点遍历一遍它周围的点,进行松弛操作,直到最终点. 整个的算法思想就是贪心,每次都给它形成最短路. 这道题目值得注意的是预处