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;

}
View Code

 

你可能感兴趣的:(dijkstra)