#include<iostream>
#include<vector>
#include<queue>
using namespace std;
const int N = 100;
const int INF = 0x3f3f3f3f;
struct Edge{ //用于记录一组关系
int u,v,w;
};
vector<Edge> edge[N]; //用于保存图的关系
int flag[N]; //用于标记是否在队列中
int dis[N]; //源点到各点的最短距离
int path[N]; //源点到各点的路径
int road[N]; //用于逆向追中输出路径
void init(int n){
for(int i=0;i<n;i++){
if(!edge[i].empty()){
edge[i].clear();
}
}
}
void SPFA_vector(int v,int n){ //源点,顶点数
int i;
memset(path,255,sizeof(path)); //初始化路径为-1;
memset(flag,false,sizeof(flag)); //初始化为false,表示不在队列
for(i=0;i<=n;i++){ //初始化dis[i]为不可到达
dis[i] = INF;
}
dis[v] = 0; //把源点到自己的路径改为0
queue<int> q; //定义一队列来维护
q.push(v); //把源点放进队列开始扩展
while(!q.empty()){
int temp = q.front(); //取队列的第一个点进行扩展
q.pop(); //出列
flag[temp]=false; //出列后标记为false
for(i=0;i<edge[temp].size();i++){ //枚举所有与该点出发的边
int w = edge[temp][i].w; //改点到下一点的权值
int v = edge[temp][i].v; //改点到下一点的顶点
if(dis[temp] + w < dis[v]){ //如果可以扩展
dis[v] = dis[temp] + w; //更新
path[v] = temp; //标记路径
if(!flag[v]){ //如果不在队列中
q.push(v); //添加进队列维护
flag[v] = true; //标记为在队列
}
}
}
}
}
int main(){
freopen("in.txt","r",stdin);
int n;
Edge temp;
while(scanf("%d",&n)!=EOF){
init(n);
while(scanf("%d%d%d",&temp.u,&temp.v,&temp.w) && ~temp.u && ~temp.v && ~temp.w){
edge[temp.u].push_back(temp); //把关系添加到vector
}
SPFA_vector(0,n);
for(int i=1;i<n;i++){
printf("%d\t",dis[i]); //输出最短路
int k=0; //用于标记要经过几个点
road[k] = i; //保存第一个点
while(path[road[k]] != -1){//若还有前继点,逆向追踪
k++;
road[k] = path[road[k-1]];
}
while(k){ //输出路径
printf("%d->",road[k--]);
}
printf("%d\n",road[k]);
}
}
return 0;
}
蓝桥:
http://lx.lanqiao.org/problem.page?gpid=T15