HDU 1385【两点间最短路, DIJK + 记录路径】

题目: http://acm.hdu.edu.cn/showproblem.php?pid=1385

解题思路:

  对每一个询问, 跑一次dijkstra算法, 麻烦的是题目要求输出路径, 有多组解时还要是字典序最小的那条.  代码复杂了点, 但思路很简单, 用一个全局变题Path[]来记录父结点就可以了, 即前一个结点, 如 : Path[i] 表示 当前点 i 是由 Path[i] 得来的.  DIJK跑完后, 可以从终点向前一直寻找前一个结点, 直到遇到始点, 可以得到一条完整的路径.

  当有多组解时, 在松驰时候要加多一个判定条件, 判断当前得出的路径的字典序是否小于以前的就可以了.

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>

using namespace std;

const int MAX = 1000 + 1;

int N;
int Cost[MAX][MAX];
int Tax[MAX];
int Dis[MAX];
int Path[MAX];
void initInput()
{
    for(int i = 1; i <= N; ++i)
    {
        for(int j = 1; j <= N; ++j)
            scanf("%d", &Cost[i][j]);
    }
    for(int i = 1; i <= N; ++i)
        scanf("%d", &Tax[i]);
}

struct comp
{
    bool operator () (const int i, const int j)
    {
        return Dis[i] > Dis[j];
    }
};
bool compare(int e1, int e2)
{
    stack<int> path1;
    stack<int> path2;
    path2.push(e1);
    while(e1 != Path[e1])
    {
        path1.push(e1);
        e1 = Path[e1];
    }
    path2.push(e1);
    while(e2 != Path[e2])
    {
        path2.push(e2);
        e2 = Path[e2];
    }
    while(!path1.empty() && !path2.empty())
    {
        if(path1.top() != path2.top())
            return path1.top() < path2.top();
        path1.pop();
        path2.pop();
    }
    return path1.size() < path2.size();
}
bool relax(int from, int to)
{
    int c = Dis[from] + Cost[from][to] + Tax[to];
    if(Cost[from][to] != -1 && c <= Dis[to])
    {
        if(c == Dis[to] && compare(to, from))
            return false;
        Dis[to] = c;
        Path[to] = from;
        return true;
    }
    else
        return false;
}
void dijk(const int start, const int end)
{
    memset(Dis, 0x7f, sizeof(Dis));
    memset(Path, 0x7f, sizeof(Path));
    int endTax = Tax[end];
    Tax[end] = 0;
    Path[start] = start;

    priority_queue<int, vector<int>, comp> que;
    Dis[start] = 0;
    que.push(start);
    while(!que.empty())
    {
        int f = que.top();
        que.pop();
        for(int i = 1; i <= N; ++i)
        {
            if(i != f && relax(f, i))
            {
                que.push(i);
            }
        }
    }
    Tax[end] = endTax;
}
void run()
{
    int start, end;
    int f, t;
    while(scanf("%d%d", &start, &end) == 2 && start != -1 && end != -1)
    {
        dijk(start, end);
        stack<int> path;
        path.push(end);

        f = end;
        while(f != start)
        {
            path.push(Path[f]);
            f = Path[f];
        }
        printf("From %d to %d :\n", start, end);
        printf("Path: %d", path.top());
        path.pop();
        while(!path.empty())
        {
            printf("-->%d", path.top());
            path.pop();
        }
        printf("\nTotal cost : %d\n\n", Dis[end]);
    }
}
int main()
{
    freopen("in.txt","r",stdin);
    while(scanf("%d", &N) == 1 && N)
    {
        initInput();
        run();
    }
    return 0;
}
posted on 2011-04-07 16:23  Kenfly  阅读(887)  评论(0编辑  收藏  举报