精华内容
下载资源
问答
  • 内某点(记为a)以边相连的点(记为b)确定其最短路径时,它的最短路径长度加上这条边的权值 结果小于a原先确定的最短路径长度,而此时a在Dijkstra算法下是无法更新的,由此便可能得不到正确的结果。 求...

    Dijkstra算法当中将节点分为已求得最短路径的集合(记为S)和未确定最短路径的个集合(记为U),
    归入S集合的节点的最短路径及其长度不再变更,如果边上的权值允许为负值,那么有可能出现当与S
    内某点(记为a)以负边相连的点(记为b)确定其最短路径时,它的最短路径长度加上这条负边的权值
    结果小于a原先确定的最短路径长度,而此时a在Dijkstra算法下是无法更新的,由此便可能得不到正确的结果。
    求带负权值边的单源最短路径可以用贝尔曼-福特算法。

    展开全文
  • 主要为大家详细介绍了C++计算任意权值的单源最短路径,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 最短路径问题 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。 Input 输入n,m,点的编号是1~n,然后是m行,...

    最短路径问题

    给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
    Input
    输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。
    (1<n<=1000, 0<m<100000, s != t)
    Output
    输出 一行有两个数, 最短距离及其花费。
    Sample Input
    3 2
    1 2 5 6
    2 3 4 5
    1 3
    0 0
    Sample Output
    9 11

    多权值最短路,用Dijkstra的优化版本,根据不同权值改改优先级队列的运算符重载

    #include<cstdio>
    #include<vector>
    #include<queue>
    using namespace std;
    struct node{
    	int v,d,p;
    	node(){}
    	node(int vv,int dd,int pp){
    		v=vv;
    		d=dd;
    		p=pp;
    	}
    }; 
    struct Node{
    	int u,d,p;
    	Node(){}
    	Node(int uu,int dd,int pp){
    		u=uu;
    		d=dd;
    		p=pp;
    	}
    	bool operator<(const Node other)const{
    	if(d!=other.d) return d>other.d;//距离短的优先
    	else return p>other.p;//如果距离一样,花费少的优先
    	}
    };
    const int maxn=1005;
    const int Inf=0x3f3f3f3f;
    int n,m,s,t;
    vector<node> G[maxn];
    bool book[maxn];
    int dis[maxn],cost[maxn];
    void Dijkstra(){
    	priority_queue<Node> q;
    	for(int i=1;i<=n;i++){
    		dis[i]=Inf,cost[i]=Inf;
    		book[i]=false;
    	}
    	dis[s]=0,cost[s]=0;
    	q.push(Node(s,dis[s],cost[s]));
    	while(!q.empty()){
    		Node temp=q.top();
    		q.pop();
    		int u=temp.u;
    		if(book[u]) continue;
    		book[u]=true;
    		for(int i=0;i<G[u].size();i++){
    			node tmp=G[u][i];
    			int v=tmp.v;
    			int d=tmp.d;
    			int p=tmp.p;
    			if(dis[v]>dis[u]+d){  
    				dis[v]=dis[u]+d;
    				cost[v]=cost[u]+p;
    				q.push(Node(v,dis[v],cost[v]));
    				continue;
    			}
    			if(dis[v]==dis[u]+d&&cost[v]>cost[u]+p){
    			    cost[v]=cost[u]+p;
    			    q.push(Node(v,dis[v],cost[v]));
    			}
    		}
    	}
    	printf("%d %d\n",dis[t],cost[t]);
    }
    int main(){
    	int a,b,d,p;
    	while(scanf("%d%d",&n,&m)){
    		if(n==0&&m==0) break;
    		for(int i=1;i<=n;i++)
    		G[i].clear();
    		for(int i=1;i<=m;i++){
    			scanf("%d%d%d%d",&a,&b,&d,&p);
    			G[a].push_back(node(b,d,p));
    			G[b].push_back(node(a,d,p));
    		}
    		scanf("%d%d",&s,&t);
    		Dijkstra();
    	}
    	return 0;
    } 
    
    
    展开全文
  • 对于一个带负权值边的有向图,实现Bellman-Ford算法,求出从指定顶点s到其余顶点的最短路径,并判断图中是否存在环。 Bellman-Ford算法的基本思路 对图中的边进行V-1轮操作(为什么是V-1轮?除了起始点,就只有V-1...

    题目描述
    对于一个带负权值边的有向图,实现Bellman-Ford算法,求出从指定顶点s到其余顶点的最短路径,并判断图中是否存在负环。
    Bellman-Ford算法的基本思路
    对图中的边进行V-1轮操作(为什么是V-1轮?除了起始点,就只有V-1个点了,一个点的最短路径经过的点的数目不会再超过V-1了,所以最多只用进行V-1轮更新),每轮都遍历图中所有的边:对每条边u->v,如果以u为中介点可以使d[v]更小,即d[u]+l[u->v]<d[v]成立时,就用d[u]+l[u->v]更新d[v](松弛操作)。V-1轮操作,每轮都遍历图中所有的边,所以Bellman-Ford算法的时间复杂度是O(VE)。
    存在问题及改进(SPFA算法)
    问题:只有当某个顶点u的d[u]值改变时,从它出发的边的邻接顶点d[v]值才可能改变(想想为什么?如果d[v]需要以u作为中介点,那d[v]一定会变,如果不需要,那么改变后的d[u])可能让u作为中介点变为一个更佳的选择。所以不需要每一轮都遍历所有边
    改进:根据上一段加粗部分说的问题,可以建立一个队列,把每次改变了d[ ]值的点加进去。每次将队首顶点u取出,然后遍历每条边u->v,进行松弛操作,对于获得了更优值的d[v],如果d[v]不在队列中,就加进去,已经在里面就不用说了。这样就有结束条件:队列为空(说明图中没有从源点可到达的负环),或者从某个顶点的入队次数超过V-1(最多用V-1次就可以把所有的点优化一次,再多就说明有个从源点可到达的负环啦,那就转一圈最短路径就变小一次,肯定是不行滴)。
    这种优化后的算法也叫做SPFA算法
    代码

    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    const int MAXV = 20;//最大顶点数
    const int INF = 100000;//无穷大
    struct Node
    {
    	int v, dis;//v为邻接边的目标顶点,dis是边权
    };
    vector<Node> Adj[MAXV];//邻接表
    int V;//顶点数
    int E;//边数
    int d[MAXV];//起点到达各点的最短路径长度
    int num[MAXV];//记录顶点的入队次数
    bool inq[MAXV];//记录顶点是否在队列里
    bool Bellman(int s)//指定顶点s
    {
    	for (int u = 0; u < V; u++)
    	{
    		d[u] = INF;
    		num[u] = 0;
    		inq[u] = false;
    	}
    	queue<int> Q;
    	Q.push(s);//源点入队
    	inq[s] = true;//源点已入队
    	num[s]++;//源点入队次数加一
    	d[s] = 0;//源点的d显然为0
    	while (!Q.empty())
    	{
    		int u = Q.front();//队首顶点编号为u
    		Q.pop();//出队
    		inq[u] = false;//设置u不在队列中
    		//遍历u的所有邻接边v
    		for (int j = 0; j < Adj[u].size(); j++)
    		{
    			int v = Adj[u][j].v;
    			int dis = Adj[u][j].dis;
    			if (d[v] > d[u] + dis)
    			{
    				d[v] = d[u] + dis;//松弛操作
    				if (!inq[v])//如果v不在队列里
    				{
    					Q.push(v);
    					inq[v] = true;
    					num[v]++;
    					if (num[v] >= V)//说明又可到达负环
    						return false;
    				}
    			}
    		}
    	}
    	return true;
    }
    int main()
    {
    	cin >> V >> E;
    	for (int i = 0; i < E; i++)
    	{
    		int u, v,dis;
    		cin >> u >> v>>dis;
    		Node e;
    		e.v = v;
    		e.dis = dis;
    		Adj[u].push_back(e);//注意一个问题vector是从0开始的
    	}
    	int s;
    	cin >> s;//指定顶点
    	bool judge = Bellman(s);
    	for (int i = 0; i < V; i++)
    	{
    		cout << "到达点"<<i<<"的最短路径是:"<<d[i]<<endl;//出从指定顶点s到其余顶点的最短路径,其中s到s的为0
    	}
    	if (!judge)
    		cout << "图中存在负环" << endl;
    	return 0;
    }
    

    测试样例与结果
    在这里插入图片描述

    6 9
    0 1 10
    1 2 -4
    0 4 4
    1 4 1
    0 5 2
    5 4 1
    4 3 6
    3 1 -5
    3 2 2
    0
    到达点0的最短路径是:0
    到达点1的最短路径是:4
    到达点2的最短路径是:0
    到达点3的最短路径是:9
    到达点4的最短路径是:3
    到达点5的最短路径是:2

    参考资料《算法笔记》胡凡
    里面有一点点是我自己的想法吧QAQ,希望自己可以通过写博客慢慢进步,最后能写出更具独创性的博客。

    展开全文
  • //更新最短路径 pre[temp2.y]=temp2.x; //保存路径前驱 } } } } //判断是否有权回路 boolean flag2=true; for(int i=0;i();i++){ Edge temp3=E.get(i); if(dist[temp3.x]!=MAX){ if(dist[temp3.x]+ ...
    https://baike.baidu.com/item/Bellman-Ford%E7%AE%97%E6%B3%95/1089090?fr=aladdin&fromid=6039406&fromtitle=bellman-ford 参考百科的c++实现版本
    import java.util.*;
    public class Bellman_Ford {
        public static void main(String args[]){
            Scanner in=new Scanner(System.in);
            while(in.hasNext()){
                int Vnum=in.nextInt();
                int Enum=in.nextInt();
                List<Edge> E=new ArrayList<Edge>();
                //输入数据
                for(int i=0;i<Enum;i++){
                    int x=in.nextInt();
                    int y=in.nextInt();
                    int value=in.nextInt();
                    int flag1=1;
                    //对边进行去重
                    for(int j=0;j<E.size();j++){
                        Edge temp1=E.get(j);
                        if(x==temp1.x && y==temp1.y){
                            if(temp1.value>value){
                                E.get(j).setValue(value);
                                flag1=0;
                                break;
                            }
                        }
                    }
                    if(flag1==1){
                        E.add(new Edge(x,y,value));
                    }
                }
                int pre[]=new int[Vnum];
                int dist[]=new int[Vnum];
                if(Bellman(0,pre,E,dist,Vnum)){
                    for(int i=1;i<Vnum;i++){
                        Print_path(0,i,pre);
                        System.out.println("="+dist[i]);
                    }
                }
            }
        }
        public static boolean Bellman(int start,int pre[],List<Edge> E,int dist[],int Vnum){
            int MAX=Integer.MAX_VALUE;
            for(int i=0;i<Vnum;i++){
                dist[i]=MAX;
            }
            dist[start]=0;
            for(int i=0;i<Vnum-1;i++){
                for(int j=0;j<E.size();j++){
                    Edge temp2=E.get(j);
                    if(dist[temp2.x]!=MAX){
                        if(dist[temp2.x]+ temp2.value<dist[temp2.y]){
                            dist[temp2.y]=dist[temp2.x]+temp2.value; //更新最短路径
                            pre[temp2.y]=temp2.x;  //保存路径前驱
                        }
                    }
                }
            }
            //判断是否有负权回路
            boolean flag2=true;
            for(int i=0;i<E.size();i++){
                Edge temp3=E.get(i);
                if(dist[temp3.x]!=MAX){
                    if(dist[temp3.x]+ temp3.value<dist[temp3.y]){
                        flag2=false;
                        break;
                    }
                }
            }
            return flag2;
        }
        //打印路径函数
        public static void Print_path(int start,int end,int pre[]){
            Stack<Integer> path=new Stack<Integer>();
            path.push(end);
            int root=end;
            while(root!=pre[root]){
                root=pre[root];
                path.push(root);
            }
            int flag3=1;
            while(path.size()>0){
                if(flag3==1){
                    System.out.print(path.pop());
                    flag3=0;
                }else{
                    System.out.print("->"+path.pop());
                }
            }
        }
    }
    //定义数据结构
    class Edge{
        int x;
        int y;
        int value;
        Edge(int x,int y,int value){
            this.x=x;
            this.y=y;
            this.value=value;
        }
        public void setValue(int value){
            this.value=value;
        }
    }
    
    展开全文
  • 原文地址:http://www.wutianqi.com/?p=1912 相关文章: 1.Dijkstra算法: ... 2.Floyd算法: ... Dijkstra算法是处理单源最短路径的有效算法,但它局限于边的权值非负的情况,若图中出现权值
  • 故不可以单纯使用路径长度计算“最短路径”,而应该使用权值字段将道路长度规划为无量纲的参数、综合道路等级、道路上设施点的数目等因素计算出一个权值字段,通过权值字段对路径进行最优化计算。 通过下午与超图...
  • 题意: 英语本来就不好,还碰上一个翻译不是行家的软件。 题意就是找出该图在符合最短路径条件下的两节点之间边的最大权值!说的应该够明白了。 思路: note:两个空行!
  • 给定如图所示的无向连通图,假定图中所有边的权值都为1,显然,从源点A到终点T的最短路径有多条,求不同的最短路径 算法分析 权值相同的最短路径问题,则单源点Dijkstra算法退化成BFS广度优先搜索,假定起点为...
  • //一个有权图的邻接矩阵经过弗洛伊德算法处理后...//和记录前驱顶点的二维数组Path[i][j](表示i到j的最短路径中j的前驱结点,如是k,则再查 //Path[i][k],如此可逆序输出i到j的最短路径);具体处理步骤看代码 voi...
  • Qt+C++校园最短路径.zip

    2019-12-29 14:54:43
    根据校园各主要生活、学习、活动等场所、地点,设计并实现基于校园各场所之间的最短路径漫游。 要求: (1)掌握数据结构的输入/输出; (2)设计与实现校园各主要场所之间的最短路径算法; (3)根据场所之间的...
  • 0.2)最短路径算法的基础知识,参见 http://blog.csdn.net/pacosonswjtu/article/details/49894021【1】Dijkstra 算法相关1.1)贪婪算法一般分阶段去求解一个问题, 在每个阶段它都把当前出现的当做是最
  • 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。   Input 输入n,m,点的编号是1~n,然后是m行,每行4个数 a...
  • 本文实例讲述了Python数据结构与算法之图的最短路径(Dijkstra算法)。分享给大家供大家参考,具体如下: # coding:utf-8 # Dijkstra算法——通过边实现松弛 # 指定一个点到其他各顶点的路径——单源最短路径 # 初始...
  • 该算法的主要思想是:利用动态绘规划的思想寻找给定的加权图中多源点之间的最短路径。每一次找到更小的路径都会更新在方阵中。 package graph.FloydAlgorithm; public class Floyd { public static void main...
  • #include #include #define INF 1000 #define MAXN 20 ... //表示是否找到最短路径 int dist[MAXN]; //表示当前最短路径的距离 int path[MAXN];//最短路径的上一个顶点 void Bellman(int v0) { int i,j,
  • 数据结构课程实践:1. 问题描述: 以顶点表示校平面图中各景点,要有景点名称、代号、简介等信息;以边表示路径,存放路径长度等信息(路径长度可以估算,以米为...(3)任意两个景点之间的最短路径。 我用java实现的
  • 问题的提法是:给定一个没有负权值的有向图和其中一个点src作为源点(source),求从点src到其余个点的最短路径及路径长度。求解该问题的算法一般为Dijkstra算法。 假设图顶点个数为n,则针对其余n-1个点需要分别找出...
  • 一、思路: 不能出现负权值的边 (1)轮流以每一个顶点为源点,重复执行Dijkstra算法n次,就可以求得每一对顶点之间的最短路径最短路径长度,总的执行时间为O(n的3次方) (2)另一种方法:用Floyd算法,总的执行...
  • 最短路径算法.rar

    2019-10-29 12:00:29
    在校园内取50个点,对选取的两点找寻最短路径,并分别以步行和骑行方式选择
  • 一、有Dijkstra算法求最短路径了,为什么还要用Bellman-Ford算法 Dijkstra算法不适合用于带有负权值的有向图。 如下图: 用Dijkstra算法求顶点0到各个顶点的最短路径: (1)首先,把顶点0添加到已访问顶点...
  • 这一部分在《啊哈!...//当一个节点扩展完后,将其出队 } cout最短路径的长度为:"测试用例: /* 测试用例 5 7 1 5 1 2 1 3 2 3 2 4 3 4 3 5 4 5 */ 结果: 最短路径的长度为:2 但是如何将路线打印出来呢?
  • 一个顶点数组就叫做最短路径,编者也太不责任了吧,好歹也给个根据得到的路径顶点数组求该路径的方法吧?还是编者想让读者有自己思考的余地??不过回头想想,如果通过那个路径顶点的二维数组,按照路径长度从小到...
  • D代表顶点到顶点的最短路径权值和的矩阵。 P代表对应顶点的最小路径的前驱矩阵。 以下程序在DEV C++中调试运行通过。 #include <stdio> #define INFINITY 65535 typedef int VertexType; //顶点是字符型 ...
  • 关键路径和最短路径

    2016-12-12 15:40:03
    关键路径
  • 处理多链路权值变大时,多链路权值增大的动态最短路径算法可有效地减少单链路权值增大动态最短路径算法的冗余计算。目前,多链路权值增大的动态最短路径算法的研究较少,尚未存在有效的多链路变大的动态最短路径...
  • 本文实例为大家分享了C++所有顶点之间最短路径的具体代码,供大家参考,具体内容如下 一、思路: 不能出现负权值的边 用Floyd算法,总的执行时间为O(n的3次方) k从顶点0一直到顶点n-1, 如果,有顶点i到顶点j之间...
  • 用c++ 实现图—邻接矩阵的最短路径算法 已经测试过。
  • 算法设计与分析实验报告,附已通过源码,供学习参考,共勉♪ 目录摘要如下: 1.问题描述 2.实验目的 3.实验原理 4.实验设计 ...(包括输入格式、算法、输出格式) ...(除了截图外,实验结果还用图表进行了分析) ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 31,375
精华内容 12,550
关键字:

最短路径处理负权值