您的位置:首页 > 其它

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

2011-04-07 16:23 281 查看
题目: 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: