#include <stdio.h>
#include <iostream>
using namespace std;
#define INF 999999
#define MAX 11000
int dist[MAX], pre[MAX], path[MAX][MAX], sum, tax[MAX];
bool sign[MAX];
void initialize(int n) //初始化
{
//sum = 0;
for(int i=1; i<=n; i++)
{
{
//pre[i] = 0;
dist[i] = INF; //将距离开始全变为最大
//sign[i] = false;
tax[i] = 0;
}
for(int j=1; j<=n; j++)
path[i][j] = INF; //图初始
}
}
/*坑爹的数据啊!Note: if there are more minimal paths, output the lexically smallest one. Print a blank line after each test case.
需要比较一下然后按字典最小输出。
4
0 2 3 9
2 0 1 5
3 1 0 3
9 5 3 1
0 0 0 0
1 4
*/
int com(int cur,int v,int a,int b)
{
int path1[MAX];
int path2[MAX];
path1[0]=cur;
path2[0]=cur;
int i=2,j=2;
path1[1]=a;
path2[1]=b;
while(a!=v)
{
path1[i++]=pre[a];
a = pre[a];
}
while(b!=v)
{
path2[j++]=pre[b];
b= pre[b];
}
while(1)
{
i--,j--;
if(i<0) return path1[1];
else if(j<0) return path2[1];
if(path1[i]<path2[j])return path1[1];
else if(path1[i]>path2[j])
return path2[1];
}
}
void dijkstra(int n, int source ,int end)
{
for(int i=1; i<=n; i++)
{
dist[i] = path[source][i]; //将与源点有关的点的距离加入dist
sign[i] = false;
if(dist[i] == INF) //确定有关系的点的前驱,无则为0
pre[i] = 0;
else
pre[i] = source;
}
dist[source] = 0; //源点自身长度为0
sign[source] = 1;
/*
依次将未放入sign集合的结点中,取dist[]最小值的结点,放入结合sign中
一旦sign包含了所有n中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
*/
for(int i=1; i<=n; i++)
{
int min = INF;
int current = source;
for(int j=1; j<=n; j++) //找出当前未使用点j的dist[j]的最小值
{
if( (!sign[j]) && (dist[j])< min )
{current = j; min = dist[j] ;}
//else if( (!sign[j]) && j == end && dist[j] < min )
//{current = j; min = dist[j];}
}
sign[current] = true; //表示当前点最短距离已经找到
for(int j=1; j<=n; j++) //更新当前点到未找到点的距离
{
if(path[current][j] == INF) continue;
int newdist =tax[current] + dist[current] + path[current][j];
if( (!sign[j]) && newdist < dist[j])
{
dist[j] = newdist;
pre[j] = current;
//if(newdist <= dist[j] )
//{dist[j] = newdist; pre[j] = current;}
}
else if(!sign[j]&& newdist == dist[j])
pre[j]= com(j,source,pre[j],current);
}
}
}
void search_path(int n, int start, int end)
{
int road[MAX];
int total = 1;
road[total++] = end; //从后向前查找
int current = pre[end]; //路径存在pre中
while( current != start) //递归查找,类似并查集
{
road[total++] = current;
sum += tax[current];
current = pre[current];
}
road[total] = start; //最后的开始点存入
printf("Path: ");
for(int i=total; i>=1; i--) //输出
{
if( i!=1)
printf("%d-->", road[i]);
else
printf("%d\n", road[i]);
}
}
void input(int line)
{
//int a, b, weight;
for(int i=1; i<=line; i++)
{
for(int j=1; j<=line; j++)
{
int weight;
scanf("%d", &weight);
//if(path[i][j] > weight && i!=j) //有多条路,保存最短的那条
{
if(weight > 0)
path[i][j] = weight;
//path[j][i] = weight; //无向图双向
}
}
}
for(int i=1; i<=line; i++)
scanf("%d", &tax[i]);
}
int main()
{
int n;
while( scanf("%d", &n)!=EOF && n)
{
initialize(n);
input(n);
int a, b;
while( scanf("%d%d", &a, &b)!=EOF && a!=-1)
{
sum = 0;
printf("From %d to %d :\n", a, b);
if(a==b){
cout <<"Path: "<<a<<endl;
cout <<"Total cost : 0"<<endl;
cout <<endl;
}
else{
dijkstra(n, a, b);
search_path(n, a, b);
printf("Total cost : %d\n\n", dist[b]);}
}
}
return 0;
}
/*
Problem Description
These are N cities in Spring country. Between each pair of cities there may be one transportation track or none. Now there is some cargo that should be delivered from one city to another. The transportation fee consists of two parts:
The cost of the transportation on the path between these cities, and
a certain tax which will be charged whenever any cargo passing through one city, except for the source and the destination cities.
You must write a program to find the route which has the minimum cost.
Input
First is N, number of cities. N = 0 indicates the end of input.
The data of path cost, city tax, source and destination cities are given in the input, which is of the form:
a11 a12 ... a1N
a21 a22 ... a2N
...............
aN1 aN2 ... aNN
b1 b2 ... bN
c d
e f
...
g h
where aij is the transport cost from city i to city j, aij = -1 indicates there is no direct path between city i and city j. bi represents the tax of passing through city i. And the cargo is to be delivered from city c to city d, city e to city f, ..., and g = h = -1. You must output the sequence of cities passed by and the total cost which is of the form:
Output
From c to d :
Path: c-->c1-->......-->ck-->d
Total cost : ......
......
From e to f :
Path: e-->e1-->..........-->ek-->f
Total cost : ......
Note: if there are more minimal paths, output the lexically smallest one. Print a blank line after each test case.
Sample Input
5
0 3 22 -1 4
3 0 5 -1 -1
22 5 0 9 20
-1 -1 9 0 4
4 -1 20 4 0
5 17 8 3 1
1 3
3 5
2 4
-1 -1
0
Sample Output
From 1 to 3 :
Path: 1-->5-->4-->3
Total cost : 21
From 3 to 5 :
Path: 3-->4-->5
Total cost : 16
From 2 to 4 :
Path: 2-->1-->5-->4
Total cost : 17
*/
附件列表
时间: 2024-10-19 00:37:52