题意:给你一个图,求其中很多点到某一点的最短路径。其实反过来就是单源最短路径,写完才发现。。。
思路:直接求最短路径,Dijkstra解之。不过要注意两点,
1.当火警位置和消防站位置相同时,path只需输出一个数。
2.倒数第二行最后多了一些空格,在zoj上我用getchar()去个换行就可以了,在poj上却错了,换成getline()就行了。
代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
#include <sstream>
using namespace std;
const int inf = 100000000;
const int maxn = 25;
struct node{
int org; //起始位置
int time; //所需时间
int index; //路径的下标
bool operator < (const node &b) const{
return time < b.time;
}
};
int n,m;
bool vis[maxn];
int dist[maxn];
int edge[maxn][maxn];
int path[maxn][maxn];
int org[maxn];
int org_cnt;
node a[maxn];
void Input(){
cin>>n;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
cin>>edge[i][j];
if(edge[i][j] == -1)
edge[i][j] = inf;
}
}
string s;
getline(cin,s);//去掉多余的换行符
getline(cin,s);
istringstream sin(s);
sin>>m;
org_cnt = 0;
while(sin>>org[org_cnt++]);
org_cnt--;
}
void Dijkstra(int u, int index){
for(int i = 1; i <= n; i++){
vis[i] = 0; dist[i] = edge[u][i];
path[index][i] = u;
}
vis[u] = 1;
dist[u] = 0;
for(int i = 0; i < n-1; i++){
int minimum = inf;
int v;
for(int j = 1; j <= n; j++){
if(dist[j] != -1 && !vis[j] && dist[j] < minimum){
minimum = dist[j]; v = j;
}
}
vis[v] = 1;
if(v == m)
break;
for(int j = 1; j <= n; j++){
if(!vis[j] && edge[v][j] != -1 && dist[v] + edge[v][j] < dist[j]){
dist[j] = dist[v] + edge[v][j];
path[index][j] = v;
}
}
}
}
void PrintPath(int index, int s){
int res[maxn];
int k = 0;
res[k] = m;
while(path[index][res[k]] != s){
k++; res[k] = path[index][res[k-1]];
}
if(s != m){
k++;
res[k] = s;
}
for(int i = k; i > 0; i--)
cout<<res[i]<<"\t";
cout<<res[0]<<"\n";
}
void Solve(){
for(int i = 0; i < org_cnt; i++){
Dijkstra(org[i],i);
a[i].index = i;
a[i].time = dist[m];
a[i].org = org[i];
}
sort(a,a+org_cnt);
cout<<"Org\tDest\tTime\tPath\n";
for(int i = 0; i < org_cnt; i++){
cout<<a[i].org<<"\t";
cout<<m<<"\t";
cout<<a[i].time<<"\t";
PrintPath(a[i].index,a[i].org);
}
}
int main(){
int t;
cin>>t;
while(t--){
Input();
Solve();
if(t)
cout<<"\n";
}
return 0;
}