#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 ",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 ",road[k]); } } return 0; }
蓝桥:
http://lx.lanqiao.org/problem.page?gpid=T15