zoukankan      html  css  js  c++  java
  • 迪杰斯特拉--- 模板(求最短路径/输出路径/所有路径都可以走的做法)

    1.0版

    #include <iostream>
    using namespace std;
     
    const int maxnum = 100;
    const int maxint = 999999;
     
    // 各数组都从下标1开始
    int dist[maxnum];     // 表示当前点到源点的最短路径长度
    int prev[maxnum];     // 记录当前点的前一个结点
    int c[maxnum][maxnum];   // 记录图的两点间路径长度
    int n, line;             // 图的结点数和路径数
     
    // n -- n nodes
    // v -- the source node
    // dist[] -- the distance from the ith node to the source node
    // prev[] -- the previous node of the ith node
    // c[][] -- every two nodes' distance
    void Dijkstra(int n, int v, int *dist, int *prev, int c[maxnum][maxnum])
    {
    	int i,j;
    	bool s[maxnum];    // 判断是否已存入该点到S集合中
    	for(i=1; i<=n; ++i)
    	{
    		dist[i] = c[v][i];
    		s[i] = 0;     // 初始都未用过该点
    		if(dist[i] == maxint)
    			prev[i] = 0;
    		else
    			prev[i] = v;
    	}
    	dist[v] = 0;
    	s[v] = 1;
     
    	// 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
    	// 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
             // 注意是从第二个节点开始,第一个为源点
    	for(i=2; i<=n; ++i)
    	{
    		int tmp = maxint;
    		int u = v;
    		// 找出当前未使用的点j的dist[j]最小值
    		for(j=1; j<=n; ++j)
    			if((!s[j]) && dist[j]<tmp)
    			{
    				u = j;              // u保存当前邻接点中距离最小的点的号码
    				tmp = dist[j];
    			}
    		s[u] = 1;    // 表示u点已存入S集合中
     
    		// 更新dist
    		for(j=1; j<=n; ++j)
    			if((!s[j]) && c[u][j]<maxint)
    			{
    				int newdist = dist[u] + c[u][j];
    				if(newdist < dist[j])
    				{
    					dist[j] = newdist;
    					prev[j] = u;
    				}
    			}
    	}
    }
     
    // 查找从源点v到终点u的路径,并输出
    void searchPath(int *prev,int v, int u)
    {
    	int que[maxnum];
    	int tot = 1;
    	que[tot] = u;
    	tot++;
    	int tmp = prev[u];
    	while(tmp != v)
    	{
    		que[tot] = tmp;
    		tot++;
    		tmp = prev[tmp];
    	}
    	que[tot] = v;
    	//输出路径
    	for(int i=tot; i>=1; --i)
    		if(i != 1)
    			cout << que[i] << " -> ";
    		else
    			cout << que[i] << endl;
    }
     
    int main()
    {
    	int i,j;
    //	freopen("input.txt", "r", stdin);
    	// 各数组都从下标1开始
     
    	// 输入结点数
    	cin >> n;
    	// 输入路径数
    	cin >> line;
    	int p, q, len;          // 输入p, q两点及其路径长度
     
    	// 初始化c[][]为maxint
    	for(i=1; i<=n; ++i)
    		for(j=1; j<=n; ++j)
    			c[i][j] = maxint;
     
    	for(i=1; i<=line; ++i)  
    	{
    		cin >> p >> q >> len;
    		if(len < c[p][q])       // 有重边
    		{
    			c[p][q] = len;      // p指向q
    			c[q][p] = len;      // q指向p,这样表示无向图
    		}
    	}
     
    	for(i=1; i<=n; ++i)
    		dist[i] = maxint;
    	//输出矩阵-------
    	for(i=1; i<=n; ++i)
    	{
    		for(j=1; j<=n; ++j)
    			printf("%8d", c[i][j]);
    		printf("
    ");
    	}
     
    	Dijkstra(n, 1, dist, prev, c);
     
    	// 最短路径长度
    	cout << "源点到最后一个顶点的最短路径长度: " << dist[n] << endl;
     
    	// 路径
    	cout << "源点到最后一个顶点的路径为: ";
    	searchPath(prev, 1, n);
    	return 0;
    }
    /*
    测试数据:
    4 4
    1 2 1
    2 3 1
    3 4 1
    1 4 4
    
    */

    1.1版 任意两点(ps:未解决负权)

    #include <iostream>
    using namespace std;
     
    const int maxnum = 100;
    const int maxint = 999999;
     
    // 各数组都从下标1开始
    int dist[maxnum];     // 表示当前点到源点的最短路径长度
    int prev[maxnum];     // 记录当前点的前一个结点
    int c[maxnum][maxnum];   // 记录图的两点间路径长度
    int n, line;             // 图的结点数和路径数
     
    // n -- n nodes
    // v -- the source node
    // dist[] -- the distance from the ith node to the source node
    // prev[] -- the previous node of the ith node
    // c[][] -- every two nodes' distance
    void Dijkstra(int n, int v, int *dist, int *prev, int c[maxnum][maxnum])
    {
    	int i,j;
    	bool s[maxnum];    // 判断是否已存入该点到S集合中
    	for(i=1; i<=n; ++i)
    	{
    		dist[i] = c[v][i];
    		s[i] = 0;     // 初始都未用过该点
    		if(dist[i] == maxint)
    			prev[i] = 0;
    		else
    			prev[i] = v;
    	}
    	dist[v] = 0;
    	s[v] = 1;
     
    	// 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
    	// 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
             // 注意是从第二个节点开始,第一个为源点
    	for(i=2; i<=n; ++i)
    	{
    		int tmp = maxint;
    		int u = v;
    		// 找出当前未使用的点j的dist[j]最小值
    		for(j=1; j<=n; ++j)
    			if((!s[j]) && dist[j]<tmp)
    			{
    				u = j;              // u保存当前邻接点中距离最小的点的号码
    				tmp = dist[j];
    			}
    		s[u] = 1;    // 表示u点已存入S集合中
     
    		// 更新dist
    		for(j=1; j<=n; ++j)
    			if((!s[j]) && c[u][j]<maxint)
    			{
    				int newdist = dist[u] + c[u][j];
    				if(newdist < dist[j])
    				{
    					dist[j] = newdist;
    					prev[j] = u;
    				}
    			}
    	}
    }
     
    // 查找从源点v到终点u的路径,并输出
    void searchPath(int *prev,int v, int u)
    {
    	int que[maxnum];
    	int tot = 1;
    	que[tot] = u;
    	tot++;
    	int tmp = prev[u];
    	while(tmp != v)
    	{
    		que[tot] = tmp;
    		tot++;
    		tmp = prev[tmp];
    	}
    	que[tot] = v;
    	//输出路径
    	for(int i=tot; i>=1; --i)
    		if(i != 1)
    			cout << que[i] << " -> ";
    		else
    			cout << que[i] << endl;
    }
     
    int main()
    {
    	int i,j;
    //	freopen("input.txt", "r", stdin);
    	// 各数组都从下标1开始
     
    	// 输入结点数
    	cin >> n;
    	// 输入路径数
    	cin >> line;
    	int p, q, len;          // 输入p, q两点及其路径长度
     
    	// 初始化c[][]为maxint
    	for(i=1; i<=n; ++i)
    		for(j=1; j<=n; ++j)
    			c[i][j] = maxint;
     
    	for(i=1; i<=line; ++i)  
    	{
    		cin >> p >> q >> len;
    		if(len < c[p][q])       // 有重边
    		{
    			c[p][q] = len;      // p指向q
    			c[q][p] = len;      // q指向p,这样表示无向图
    		}
    	}
     
    	for(i=1; i<=n; ++i)
    		dist[i] = maxint;
    	//输出矩阵-------
    	for(i=1; i<=n; ++i)
    	{
    		for(j=1; j<=n; ++j)
    			printf("%8d", c[i][j]);
    		printf("
    ");
    	}
    	int begin,end;
    	printf("输入起点和终点
    ");
    	scanf("%d%d",&begin,&end);
    	Dijkstra(end, begin, dist, prev, c);
     
    	// 最短路径长度
    	cout << "点A到点B的最短路径长度: " << dist[n] << endl;
     
    	// 路径
    	cout << "点A到点B的路径为: ";
    	searchPath(prev, begin, end);
    	return 0;
    }
    /*
    测试数据:
    4 4
    1 2 1
    2 3 1
    3 4 1
    1 4 4
    2 2
    cout<<
    2
    2->3->4
    */


    if 题目要求的是每两点之间的路都可以走或可以求的话,用下面方法


    #include <iostream>
    using namespace std;
    
    const int maxnum = 100;
    const int maxint = 999999;
     struct Point{
    	double x;
    	double y;
    	double len;
    }p[250];
    // 各数组都从下标1开始
    int dist[maxnum];     // 表示当前点到源点的最短路径长度
    int prev[maxnum];     // 记录当前点的前一个结点
    int c[maxnum][maxnum];   // 记录图的两点间路径长度
    int n, line;             // 图的结点数和路径数
    
    // n -- n nodes
    // v -- the source node
    // dist[] -- the distance from the ith node to the source node
    // prev[] -- the previous node of the ith node
    // c[][] -- every two nodes' distance
    void Dijkstra(int n, int v, int *dist, int *prev, int c[maxnum][maxnum])
    {
    	int i,j;
    	bool s[maxnum];    // 判断是否已存入该点到S集合中
    	for(i=1; i<=n; ++i)
    	{
    		dist[i] = c[v][i];
    		s[i] = 0;     // 初始都未用过该点
    		if(dist[i] == maxint)
    			prev[i] = 0;
    		else
    			prev[i] = v;
    	}
    	dist[v] = 0;
    	s[v] = 1;
    
    	// 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
    	// 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度
             // 注意是从第二个节点开始,第一个为源点
    	for(i=2; i<=n; ++i)
    	{
    		int tmp = maxint;
    		int u = v;
    		// 找出当前未使用的点j的dist[j]最小值
    		for(j=1; j<=n; ++j)
    			if((!s[j]) && dist[j]<tmp)
    			{
    				u = j;              // u保存当前邻接点中距离最小的点的号码
    				tmp = dist[j];
    			}
    		s[u] = 1;    // 表示u点已存入S集合中
    
    		// 更新dist
    		for(j=1; j<=n; ++j)
    			if((!s[j]) && c[u][j]<maxint)
    			{
    				int newdist = dist[u] + c[u][j];
    				if(newdist < dist[j])
    				{
    					dist[j] = newdist;
    					prev[j] = u;
    				}
    			}
    	}
    }
    
    // 查找从源点v到终点u的路径,并输出
    void searchPath(int *prev,int v, int u)
    {
    	int que[maxnum];
    	int tot = 1;
    	que[tot] = u;
    	tot++;
    	int tmp = prev[u];
    	while(tmp != v)
    	{
    		que[tot] = tmp;
    		tot++;
    		tmp = prev[tmp];
    	}
    	que[tot] = v;
    	//输出路径
    	for(int i=tot; i>=1; --i)
    		if(i != 1)
    			cout << que[i] << " -> ";
    		else
    			cout << que[i] << endl;
    }
    
    int main()
    {
    	int i,j;
    //	freopen("input.txt", "r", stdin);
    	// 各数组都从下标1开始
    
    	// 输入结点数
    //	cin >> n;
    	// 输入路径数
    //	cin >> line;
    	double x1,y1,x2,y2;
    	cin>>x1>>y1>>x2>>y2;
    	double p, q, len;          // 输入p, q两点及其路径长度
    
    	// 初始化c[][]为maxint
    	for(int i=1;;i++){
    		cin>>p[i].x>>p[i].y;
    	}
    	for(i=1; i<=n; ++i)
    		for(j=1; j<=n; ++j)
    			c[i][j] = maxint;
    
    	for(i=1; i<=line; ++i)
    	{
    		cin >> p >> q >> len;
    		if(len < c[p][q])       // 有重边
    		{
    			c[p][q] = len;      // p指向q
    			c[q][p] = len;      // q指向p,这样表示无向图
    		}
    	}
    
    	for(i=1; i<=n; ++i)
    		dist[i] = maxint;
    	//输出矩阵-------
    	for(i=1; i<=n; ++i)
    	{
    		for(j=1; j<=n; ++j)
    			printf("%8d", c[i][j]);
    		printf("
    ");
    	}
    	int begin,end;
    	printf("输入起点和终点
    ");
    	scanf("%d%d",&begin,&end);
    	Dijkstra(end, begin, dist, prev, c);
    
    	// 最短路径长度
    	cout << "点A到点B的最短路径长度: " << dist[n] << endl;
    
    	// 路径
    	cout << "点A到点B的路径为: ";
    	searchPath(prev, begin, end);
    	return 0;
    }
    /*
    测试数据:
    4 4
    1 2 1
    2 3 1
    3 4 1
    1 4 4
    2 2
    cout<<
    2
    2->3->4
    */
    


    版权声明:本文为博主原创文章,未经博主允许不得转载。

    today lazy . tomorrow die .
  • 相关阅读:
    GetHub下载不成功
    Cache 判断Ip几分钟内攻击次数
    .net 通过Url获取站点json数据
    Linq 读取Xml 数据
    ef Linq 自定义字段列表
    面试的心得
    触发器--单独字段变化另一个字段也变化
    Ajax跨域 取值 Jsonp的定义注意事项
    asp.net里,各种下载方式汇总
    c# 获取硬件信息
  • 原文地址:https://www.cnblogs.com/france/p/4808741.html
Copyright © 2011-2022 走看看