最短経路問題(HDU 3790)

トピックリンク

タイトル説明

もしn点、m個の物品は、複数の経路と、各エッジは、長さdと費用pを有するあなたが最後tを開始だ、そのコストの終わりに開始点からの最短距離が必要であり、最短距離をエッジを無向最も安価なの出力。

入力形式

入力N、M点の数は、1〜Nは、m行であり、各行番号4、A、B、D、Pは、間、Bにエッジがあることを示し、およびDの長さは、P費やされています。原点S、END;最後の行番号は、T 2 sです。mが0であり、n個の入力端です。(1 <N <= 1000、0 <M <100000、よ!= T)

出力フォーマット

出力二つの数字、最短距離とコストとのライン。

サンプル入力

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

サンプル出力

9 11

分析

最短D費、もう一つの裁判官は、ライン上の最小コストを更新するためにテンプレートを適用しながら、以下ではそれぞれダイクストラ、SPFA、SPFA(SLF最適化)アルゴリズムのソースコードです。

ソース

ダイクストラ法

#include <bits/stdc++.h>
#define MAXN 1005
#define MAXM 100005
using namespace std;
struct Edge{	//链式前向星建图 
	int v,w,c,next;
	Edge(){};
	Edge(int _v,int _w,int _c,int _next){
		v=_v,w=_w,c=_c,next=_next;
	};
	bool operator <(const Edge a)const{
		if(w!=a.w)return w>a.w;
		else return c>a.c;
	}
}edge[MAXM*2];
int EdgeCount,head[MAXN];
int n,m,s,t,dis[MAXN],cost[MAXN];
bool used[MAXN];
void addEdge(int u,int v,int w,int c)	//链式前向星加边 
{
	edge[++EdgeCount]=Edge(v,w,c,head[u]);
	head[u]=EdgeCount;
}
void dijkstra()
{
	memset(dis,0x3f,sizeof(dis));	//初始化 
	memset(cost,0x3f,sizeof(cost));
	memset(used,false,sizeof(used));
	priority_queue<Edge> q;
	dis[s]=cost[s]=0;
	q.push(Edge{s,0,0,0});
	while(!q.empty()){
		int u=q.top().v;q.pop();
		if(used[u])continue;	//如果已经确定最短路就continue 
		used[u]=true;
		for(int i=head[u];i;i=edge[i].next){
			int v=edge[i].v,w=edge[i].w,c=edge[i].c;
			if(dis[v]>dis[u]+w){	//找到新的最短路 
				dis[v]=dis[u]+w;
				cost[v]=cost[u]+c;
				q.push(Edge{v,dis[v],cost[v],0});
			}
			else if(dis[v]==dis[u]+w){	//找到新的最短路最小费用 
				if(cost[v]>cost[u]+w){
					cost[v]=cost[u]+c;
				}
			}
		}
	}
	return ;
}
int main()
{
	while(scanf("%d%d",&n,&m)&&(n||m)){
		memset(head,0,sizeof(head));	//初始化 
		EdgeCount=0;
		for(int i=1;i<=m;i++){	//读入数据 
			int u,v,w,c;
			scanf("%d%d%d%d",&u,&v,&w,&c);
			addEdge(u,v,w,c);
			addEdge(v,u,w,c);
		}
		scanf("%d%d",&s,&t);	//读入起点和终点 
		dijkstra();
		printf("%d %d\n",dis[t],cost[t]);
	}
}

SPFAアルゴリズム

#include <bits/stdc++.h>
#define MAXN 1005
#define MAXM 100005
using namespace std;
struct Edge{
	int v,w,c,next;
	Edge(){};
	Edge(int _v,int _w,int _c,int _next){
		v=_v,w=_w,c=_c,next=_next;
	};
}edge[MAXM];
int EdgeCount,head[MAXN];
int n,m,s,t,dis[MAXN],cost[MAXN];
int ven[MAXN],nums[MAXN];
void addEdge(int u,int v,int w,int c)
{
	edge[++EdgeCount]=Edge(v,w,c,head[u]);
	head[u]=EdgeCount;	
} 
void SPFA()
{
	memset(dis,0x3f,sizeof(dis));
	memset(cost,0x3f,sizeof(cost));
	memset(ven,0,sizeof(ven));
	memset(nums,0,sizeof(nums));
	queue<int> q;
	dis[s]=cost[s]=0;
	ven[s]=nums[s]=1;
	q.push(s);
	while(!q.empty()){
		int u=q.front();q.pop();
		ven[u]=0;
		for(int i=head[u];i;i=edge[i].next){
			int v=edge[i].v,w=edge[i].w,c=edge[i].c;
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				cost[v]=cost[u]+c;
				if(!ven[v]){
					q.push(v);
					ven[v]=1;
//					nums[v]++;
//					if(nums[v]>n)return false;
				}
			}
			else if(dis[v]==dis[u]+w){
				if(cost[v]>cost[u]+c){
					cost[v]=cost[u]+c;
					if(!ven[v]){
						q.push(v);
						ven[v]=1;
//						nums[v]++;
//						if(nums[v]>n)return false;
					}
				}
			}
		}
	}
//	return true;
}
int main()
{
	while(scanf("%d%d",&n,&m)&&(n||m)){
		memset(head,0,sizeof(head));
		EdgeCount=0;
		for(int i=1;i<=m;i++){
			int u,v,w,c;
			scanf("%d%d%d%d",&u,&v,&w,&c);
			addEdge(u,v,w,c);
			addEdge(v,u,w,c);
		}
		scanf("%d%d",&s,&t);
		SPFA();
		printf("%d %d\n",dis[t],cost[t]);
	}
}

SLF SPFAアルゴリズムの最適化

#include <bits/stdc++.h>
#define MAXN 1005
#define MAXM 100005
using namespace std;
struct Edge{	//链式前向星 
	int v,w,c,next;
	Edge(){};
	Edge(int _v,int _w,int _c,int _next){
		v=_v,w=_w,c=_c,next=_next;
	};
}edge[MAXM];
int EdgeCount,head[MAXN];
int n,m,s,t,dis[MAXN],cost[MAXN];
int ven[MAXN],nums[MAXN];
void addEdge(int u,int v,int w,int c) //链式前向星加边 
{
	edge[++EdgeCount]=Edge(v,w,c,head[u]);
	head[u]=EdgeCount;	
} 
void SPFA()
{
	memset(dis,0x3f,sizeof(dis));	//初始化 
	memset(cost,0x3f,sizeof(cost));
	memset(ven,0,sizeof(ven));
	memset(nums,0,sizeof(nums));
	deque<int> q;
	dis[s]=cost[s]=0;
	ven[s]=nums[s]=1;
	q.push_back(s);
	int cnt;
	while((cnt=q.size())){
		int u=q.front();q.pop_front();
		ven[u]=0;	//取消队列标记 
		for(int i=head[u];i;i=edge[i].next){
			int v=edge[i].v,w=edge[i].w,c=edge[i].c;
			if(dis[v]>dis[u]+w){	//更新最短路 
				dis[v]=dis[u]+w;
				cost[v]=cost[u]+c;
				if(!ven[v]){	//不在队列中 
					if(cnt>1&&dis[v]<dis[q.front()])q.push_front(v);
					else q.push_back(v); 
					ven[v]=1;
//					nums[v]++;
//					if(nums[v]>n)return false;
				}
			}
			else if(dis[v]==dis[u]+w){	//更新最短路最小费用 
				if(cost[v]>cost[u]+c){
					cost[v]=cost[u]+c;
				}
			}
		}
	}
//	return true;
}
int main()
{
	while(scanf("%d%d",&n,&m)&&(n||m)){
		memset(head,0,sizeof(head));	//初始化 
		EdgeCount=0;
		for(int i=1;i<=m;i++){	//读入数据 
			int u,v,w,c;
			scanf("%d%d%d%d",&u,&v,&w,&c);
			addEdge(u,v,w,c);
			addEdge(v,u,w,c);
		}
		scanf("%d%d",&s,&t);	//读入起点和终点 
		SPFA();
		printf("%d %d\n",dis[t],cost[t]);
	}
}
公開された19元の記事 ウォンの賞賛0 ビュー125

おすすめ

転載: blog.csdn.net/weixin_43960284/article/details/105269428