首页 > 其他 > 详细

题解:最短路径

时间:2021-04-27 22:14:44      阅读:34      评论:0      收藏:0      [点我收藏+]

技术分享图片

解析:

这道最短路径的问题,我们还是采用拓扑的思路,反着存图,往回加,走最短的,如果从边上绕路比直接过去省距离,那么就从边上绕路。
还有值得一提的是链式前向星的记录路径:
if(e[i].w + dp[now] < dp[u]){ dp[u] = e[i].w + dp[now]; path[u] = now; }
输出如下:
for(int i = 1;path[i];i=path[i])printf("%d " ,path[i]);
前一个点记录的是自己的前一个端点

完整代码如下:

#include <bits/stdc++.h>
using namespace std;

struct Edge{
    int to,nxt,w;
}e[1000001];

int head[100001];
int ecnt = -1;
int n;
int ru[100001];

void addEdge(int x,int y,int w){
    e[++ecnt] = (Edge){y,head[x],w};
    head[x] = ecnt;
}

queue <int> q;
int dp[100001];
int path[1000001];
int id = 1;

void topo_sort(){
    for(int i = 1;i <= n; i++){
	    if(ru[i] == 0) q.push(i);
	    dp[i] = 1e9;
    }
    dp[n] = 0;
    while(!q.empty()){
	    int now = q.front();q.pop();
	    for(int i = head[now]; ~i; i = e[i].nxt){
		    int u = e[i].to;
		    if(e[i].w + dp[now] < dp[u]){
			    dp[u] = e[i].w + dp[now];
			    path[u] = now;
		    }
		    if(!--ru[u]){
			    q.push(u);
		    }
	    }
    }
}

int main()
{
    scanf("%d" ,&n);
    memset(head,-1,sizeof(head));
    for(int i = 1;i <= n; i++){
	    for(int j = 1;j <= n; j++){
		    int c;
		    scanf("%d" ,&c);
		    if(c != 0){
			    addEdge(j,i,c);
			    ru[i]++;
		    }
	    }
    }
    topo_sort();
    printf("%d\n" ,dp[1]);
    for(int i = 1;path[i];i=path[i])printf("%d " ,path[i]);
    return 0;	
}

样例:

技术分享图片

题解:最短路径

原文:https://www.cnblogs.com/Crazyman-W/p/14710739.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!