zoukankan      html  css  js  c++  java
  • 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
    ");
            else
                printf("%.0lf
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    HDU 1261 字串数(排列组合)
    Codeforces 488C Fight the Monster
    HDU 1237 简单计算器
    POJ 2240 Arbitrage
    POJ 3660 Cow Contest
    POJ 1052 MPI Maelstrom
    POJ 3259 Wormholes
    POJ 3268 Silver Cow Party
    Codesforces 485D Maximum Value
    POJ 2253 Frogger(最短路)
  • 原文地址:https://www.cnblogs.com/wd-one/p/4519170.html
Copyright © 2011-2022 走看看