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
  • 相关阅读:
    Visual Studio DSL 入门 11为状态机设计器添加规则
    不平静的2009,期待更不平静的2010
    ASP.NET MVC 2 正式发布
    [翻译] DSL和模型驱动开发的最佳实践(2/4)
    Visual Studio DSL 入门 9创建状态机的图形符号
    Visual Studio DSL 入门 6DSL的图形表示1
    智诚B2C1.31正式发
    一个程序员的创业尝试
    Visual Studio DSL 入门 13结合T4生成代码
    Visual Studio DSL 入门 10完善状态机案例
  • 原文地址:https://www.cnblogs.com/wd-one/p/4519170.html
Copyright © 2011-2022 走看看