• Dijkstra实现最短路径


    #include<cstdio>
    #include<iostream> 
    #include<algorithm>
    using namespace std;
    const int MAXV=1000;
    const int INF=100000000;
    int n,m,s,G[MAXV][MAXV];
    int d[MAXV];//起点到达各点的最短路径长度
    bool vis[MAXV]={false};
    void Dijkstra(int s){
    	fill(d,d+MAXV,INF);
    	d[s]=0;
    	for(int i=0;i<n;i++){
    		int u=-1,MIN=INF;
    		for(int j=0;j<n;j++){
    			if(vis[j]==false&&d[j]<MIN){
    				u=j;
    				MIN=d[j];
    			}
    		}
    	if(u==-1) return;
    	vis[u]=true;
    	for(int v=0;v<n;v++){
    		if(vis[v]==false&&G[u][v]!=INF&&d[u]+G[u][v]<d[v]){
    			d[v]=d[u]+G[u][v];
    		}
    	}
    }
    }
    int main(){
    	int u,v,w;
    	cin>>n>>m>>s;
    	fill(G[0],G[0]+MAXV*MAXV,INF);
    	for(int i=0;i<m;i++){
    		cin>>u>>v>>w;
    		G[u][v]=w;
    	}
    	Dijkstra(s);
    	for(int i=0;i<n;i++){
    		cout<<d[i]<<" ";
    	}
    	return 0;
    }
    



    邻接表实现

    #include<cstdio>
    #include<iostream> 
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int INF=1000000;
    const int MAXV=30;
    int m,s,n,d[MAXV];//m个点n个边起点是s 
    bool vis[MAXV]={false};
    struct Node{
        int v,dis;
    };
    vector<Node>G[MAXV];
    void dj(){
        fill(d,d+MAXV,INF);
        d[s]=0;
        for(int i=0;i<m;i++){
            int u=-1,MAX=INF;
            for(int j=0;j<m;j++){
                if(vis[j]==false&&d[j]<MAX){
                    u=j;
                    MAX=d[j];
                }
            }
            if(u==-1) return;
            vis[u]=true;
            for(int j=0;j<G[u].size();j++){
                int v=G[u][j].v;
                if(vis[v]==false&&d[u]+G[u][j].dis<d[v]){
                    d[v]=d[u]+G[u][j].dis;//注意此处是G[u][j]而不是G[u][v]
                }
            }
        }
    }
    int main(){
        int uu,vv,w;
        cin>>m>>n>>s;
        for(int i=0;i<n;i++){
            cin>>uu>>vv>>w;
            Node tp;
            tp.dis=w;
            tp.v=vv;
            G[uu].push_back(tp);
        }
        dj();
        for(int i=0;i<m;i++){
            cout<<d[i]<<" ";
        }
        return 0;
    }

    测试:

    6 8 0

    0 1 1

    0 3 4

    0 4 4

    1 3 2

    2 5 1

    3 2 2

    3 4 3

    4 5 3

    代码解释:

     void d(){
    	//初始化图
    	//将出发点到出发点的距离设为0 
    	for(循环n次){//n表示顶点数 
    	//设当前欲访问的顶点下标为u=-1;
    	//设所有点中到起点距离最短的那个点的路径长为MAX=100000000000; 
    	for(循环n次){
    		if(第n个点没有被访问&&该点到起点的路径最短){
    			MAX=最短路径;
    			u=n;//记录该点,即该点已经被访问 
    		}
    	} 
    	if(u==-1) return;//所有点已经被访问,函数结束
    	//标记u点被访问
    	for(n次循环){
    		if(该点没有被访问&&该点到新被访问顶点u的距离小于原来路径){
    			//更新路径 
    		}
    	} 
    	}		
    }
    

      视频解释:https://www.bilibili.com/video/av38254646/?redirectFrom=h5

    时间复杂度=n*(n+n)

    在实际解题中可能会出现多个权重的问题,直接的解题方法就是增加变量再重新划分逻辑,例如PAT A1003

    As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.

    Input

    Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (<= 500) – the number of cities (and the cities are numbered from 0 to N-1), M – the number of roads, C1 and C2 – the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c1, c2 and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C1 to C2.

    Output

    For each test case, print in one line two numbers: the number of different shortest paths between C1 and C2, and the maximum amount of rescue teams you can possibly gather.
    All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.

    Sample Input

    5 6 0 2
    1 2 1 5 3
    0 1 1
    0 2 2
    0 3 1
    1 2 1
    2 4 1
    3 4 1

    Sample Output

    2 4

    #include<iostream> 
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int MAXV=510;
    const int INF=10000000;
    bool vis[MAXV]={false};
    int n,m,s,e,G[MAXV][MAXV],d[MAXV],num[MAXV],weight[MAXV],w[MAXV];
    void dj(){
    	fill(d,d+MAXV,INF);
    	memset(num,0,sizeof(num));
    	memset(w,0,sizeof(w));
    	d[s]=0;
    	w[s]=weight[s];
    	num[s]=1;
    	for(int i=0;i<n;i++){
    		int MIN=INF,u=-1;
    		for(int j=0;j<n;j++){
    			if(vis[j]==false&&d[j]<MIN){
    				u=j;
    				MIN=d[j];
    			}
    		}
    		if(u==-1) return;
    		vis[u]=true;
    		for(int v=0;v<n;v++){
    			if(vis[v]==false&&G[u][v]!=INF){
    				if(d[u]+G[u][v]<d[v]){
    				d[v]=d[u]+G[u][v];
    				w[v]=w[u]+weight[v];
    				num[v]=num[u];
    				}else if(d[u]+G[u][v]==d[v]){
    				if(w[u]+weight[v]>w[v]){
    					w[v]=weight[v]+w[u];
    				}
    					num[v]+=num[u];
    			}
    		}
    	}
    }
    }
    int main(){
    	
    	cin>>n>>m>>s>>e;
    	for(int i=0;i<n;i++){
    		cin>>weight[i];
    	}
    	int u,v,p;
    	fill(G[0],G[0]+MAXV*MAXV,INF);
    	for(int i=0;i<m;i++){
    		cin>>u>>v>>p;
    		G[v][u]=G[u][v]=p;
    	}
    	dj();
    	cout<<num[e]<<" "<<w[e];
    	return 0; 
    }
    

      还有PAT A1030

    A traveler's map gives the distances between cities along the highways, together with the cost of each highway. Now you are supposed to write a program to help a traveler to decide the shortest path between his/her starting city and the destination. If such a shortest path is not unique, you are supposed to output the one with the minimum cost, which is guaranteed to be unique.

    Input Specification:

    Each input file contains one test case. Each case starts with a line containing 4 positive integers N, M, S, and D, where N (≤) is the number of cities (and hence the cities are numbered from 0 to N1); M is the number of highways; S and D are the starting and the destination cities, respectively. Then M lines follow, each provides the information of a highway, in the format:

    City1 City2 Distance Cost
    

    where the numbers are all integers no more than 500, and are separated by a space.

    Output Specification:

    For each test case, print in one line the cities along the shortest path from the starting point to the destination, followed by the total distance and the total cost of the path. The numbers must be separated by a space and there must be no extra space at the end of output.

    Sample Input:

    4 5 0 3
    0 1 1 20
    1 3 2 30
    0 3 4 10
    0 2 2 20
    2 3 1 20
    

    Sample Output:

    0 2 3 3 40

    增加变量的常规解法
    #include<iostream> 
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int MAXV=510;
    const int INF=100000000;
    bool vis[MAXV]={false};
    int n,m,s,e,G[MAXV][MAXV],d[MAXV],cost[MAXV],weight[MAXV][MAXV],pre[MAXV];
    void dj(){
    	fill(d,d+MAXV,INF);
    	fill(cost,cost+MAXV,INF);
    	cost[s]=0;
    	d[s]=0;
    	for(int i=0;i<n;i++)
    	pre[i]=i;
    	for(int i=0;i<n;i++){
    		int MIN=INF,u=-1;
    		for(int j=0;j<n;j++){
    			if(vis[j]==false&&d[j]<MIN){
    				u=j;
    				MIN=d[j];
    			}
    		}
    		//if(u==-1) return;
    		vis[u]=true;
    		for(int v=0;v<n;v++){
    			if(vis[v]==false&&G[u][v]!=INF){
    				if(d[v]>d[u]+G[u][v]){
    					d[v]=d[u]+G[u][v];
    					cost[v]=cost[u]+weight[u][v];
    				pre[v]=u;
    				}else if(d[v]==d[u]+G[u][v]&&cost[u]+weight[u][v]<cost[v]){
    					cost[v]=cost[u]+weight[u][v];
    				pre[v]=u;
    				}
    			}
    		}
    	}
    }
    void f(int v){
    	if(v==s){
    		cout<<v<<" ";
    		return;
    	}
    	f(pre[v]);
    	cout<<v<<" ";
    }
    int main(){
    	cin>>n>>m>>s>>e;
    	int u,v,p,q;
    	fill(G[0],G[0]+MAXV*MAXV,INF);
    	for(int i=0;i<m;i++){
    		cin>>u>>v>>p>>q;
    		
    		weight[v][u]=weight[u][v]=q;
    		G[v][u]=G[u][v]=p;
    	}
    	dj();
    	f(e); 
    	cout<<d[e]<<" "<<cost[e];
    	return 0; 
    }
    

      

     模板式DFS+dj

    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int INF=100000000;
    const int MAXV=510;
    int d[MAXV],c[MAXV],G[MAXV][MAXV],cost[MAXV][MAXV];
    bool vis[MAXV]={false};
    int n,m,s,e,mincost=INF;
    vector<int>pre[MAXV];
    vector<int>temppath,path;
    void dj(){
    	fill(d,d+MAXV,INF);
    	d[s]=0;
    	for(int i=0;i<n;i++){
    		int MIN=INF,u=-1;
    		for(int j=0;j<n;j++){
    			if(vis[j]==false&&d[j]<MIN){
    				MIN=d[j];
    				u=j;
    			}
    		}
    		if(u==-1) return;
    		vis[u]=true;
    		for(int v=0;v<n;v++){
    			if(vis[v]==false&&G[u][v]!=INF){
    				if(d[v]>d[u]+G[u][v]){
    					d[v]=d[u]+G[u][v];
    					pre[v].clear();
    					pre[v].push_back(u);
    				}else if(d[v]==d[u]+G[u][v]){
    					pre[v].push_back(u);
    				}
    				
    			}
    		}
    	}
    }
    void DFS(int v){
    	if(v==s){
    		temppath.push_back(v);
    		int tempcost=0;
    		for(int i=temppath.size()-1;i>0;i--){
    			int id=temppath[i],idnext=temppath[i-1];
    			tempcost+=cost[id][idnext];
    		}
    		if(tempcost<mincost){
    			mincost=tempcost;
    			path=temppath;
    		}
    		temppath.pop_back();
    		return;
    	}
    	temppath.push_back(v);
    	for(int i=0;i<pre[v].size();i++)
    	DFS(pre[v][i]);
    	temppath.pop_back();
    }
    int main(){
    	cin>>n>>m>>s>>e;
    	int a,b,c,dd;
    	fill(G[0],G[0]+MAXV*MAXV,INF);
    	fill(cost[0],cost[0]+MAXV*MAXV,INF);
    	for(int i=0;i<m;i++){
    		cin>>a>>b>>c>>dd;
    		G[a][b]=G[b][a]=c;
    		cost[a][b]=cost[b][a]=dd;
    	}
    	dj();
    	DFS(e);
    	for(int i=path.size()-1;i>=0;i--)
    	cout<<path[i]<<" ";
    	cout<<d[e]<<" "<<mincost;
    }
    

      

    关于该算法的题目和思想后续还会更新

  • 相关阅读:
    VMware虚拟机Mac OS X无法调整扩展硬盘大小,更新xcode时出现磁盘空间不足
    打包时Xcode报:此证书的签发者无效Missing iOS Distribution signing identity
    iPhone私有API
    Xcode真机调试中"There was an internal API error"错误解决方法
    用C#通过反射实现动态调用WebService 告别Web引用
    MySQL、PostgreSQL、Ingres r3、MaxDB等开源数据库的详细比较
    jQuery Mobile 移动开发中的日期插件Mobiscroll使用说明
    SQL Server 2008|2012 阻止保存要求重新创建表的更改
    SQL Server如何启用xp_cmdshell组件
    Windows平台下利用APM来做负载均衡方案
  • 原文地址:https://www.cnblogs.com/tao7/p/10237406.html
Copyright © 2020-2023  润新知