最短路径问题

1.Floyd(多源点最短路径)

#include<cstdio>
#include<cstdlib>
#include<cstring>

using namespace std;

int n,m,dist[110][110];//dist[i][j]i->j的最短路长度是多少

int main()
{
	scanf("%d%d",&n,&m);

	memset(dist,0x3f,sizeof(dist));//for i,j dist[i][j]=0x3f3f3f3f;
	for (int a=1;a<=n;a++)
		dist[a][a] = 0;
	for (int a=1;a<=m;a++)
	{
		int s,e,d;
		scanf("%d%d%d",&s,&e,&d);
		dist[s][e]=min(dist[s][e],d);
	}

	//O(n^3) 
	//1. 多源最短路问题
	//2. n<=200
	for (int i=1;i<=n;i++)//枚举中间点
		for (int j=1;j<=n;j++)//枚举起点
			for (int k=1;k<=n;k++)//枚举终点
				dist[j][k] = min(dist[j][k], dist[j][i]+dist[i][k]);


}

2.dijkstra(O(n^2))

#include<cstdio>
#include<cstdlib>
#include<cstring>

using namespace std;

int dist[maxn];//dist[i]代表起点到i号点的最短路长度

bool right[maxn];//代表第i个点是否在右边

void dijkstra(int s)//s是起点
{
	memset(dist,0x3f,sizeof(dist));//0x3f3f3f3f
	dist[s]=0;
	for (int a=1;a<=n;a++)//O(n^2+m)
	{
		int p=-1;
		for (int b=1;b<=n;b++)//O(n^2)
			if (!right[b] && (p==-1 || dist[b]<dist[p])) p=b;
		right[p]=true;
		for (int b=first[p];b!=0;b=ed[b].next)//O(m)
		{
			int e=ed[b].e,d=ed[b].d;//p -> e 长度为d的边
			dist[e] = min(dist[e],dist[p]+d);
		}
	}
}

int main()
{
	scanf("%d%d",&n,&m);
	for (int a=1;a<=m;a++)
	{
		int s,e,d;
		scanf("%d%d%d",&s,&e,&d);
		add_edge(s,e,d);
	}
	dijkstra(1);

	return 0;
}

3.dijkstra堆优化(O((n+m)*log(n+m)))

#include<iostream>
#include<queue> 
#include<stdio.h>
using namespace std;
struct node{
	int p,d;
};
bool operator<(const node &a,const node &b){
	return a.d>b.d;
}
priority_queue<node>q;
struct rec{
	int e,d,nex;
}a[500010];
long long dis[100010];
int n,m,s,en,first[100010];
bool vis[100010];
void add(int x,int y,int z){
	en++;
	a[en].e=y;
	a[en].d=z;
	a[en].nex=first[x];
	first[x]=en;
}
long long f(int x,int y){
	if (y==0) return 1;
	long long v=f(x,y>>1);
	v=v*v;
	if (y&1==1){
		v*=x;
	}
	return v;
}
void dj(int ccf){
	for (int i=1;i<=n;i++) dis[i]=f(2,31)-1;
	dis[ccf]=0;
	for (int i=1;i<=n;i++){
		node x;
		x.p=i;
		x.d=dis[i];
		q.push(x);
	}
	for (int j=1;j<=n;j++){
		while (vis[q.top().p]==true){
			q.pop();
		}
		node x=q.top();
		q.pop();
		int p=x.p;
		vis[p]=true;
		for (int i=first[p];i!=0;i=a[i].nex){
			int e=a[i].e;
			int d=a[i].d;
			if (dis[e]>dis[p]+d){
				dis[e]=dis[p]+d;
				node y;
				y.p=e;
				y.d=dis[e];
				q.push(y);
			}
		}
	}
}
int main(){
	//freopen("1.txt","r",stdin);
	//freopen("2.txt","w",stdout);
	scanf("%d%d%d",&n,&m,&s);
	for (int i=1;i<=m;i++){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
	}
	dj(s);
	for (int i=1;i<=n;i++){
		printf("%lld ",dis[i]);
	}
	return 0;
}

4.Bellman-Ford(O(nm))

#include<iostream>
#include<stdio.h>
using namespace std;
int n,m,st,s[500010],e[500010],d[500010];
long long dis[100010];
long long f(int x,int y){
	if (y==0) return 1;
	long long v=f(x,y>>1);
	v=v*v;
	if (y&1==1){
		v=v*x;
	}
	return v;
}
int main(){
	scanf("%d%d%d",&n,&m,&st);
	for (int i=1;i<=m;i++){
		scanf("%d%d%d",&s[i],&e[i],&d[i]);
	}
	for (int i=1;i<=n;i++){
		dis[i]=f(2,31)-1;
	}
	dis[st]=0;
	for (int i=1;i<n;i++){
		for (int j=1;j<=m;j++){
			dis[e[j]]=min(dis[e[j]],dis[s[j]]+d[j]);
		}
	}
	for (int i=1;i<=n;i++){
		printf("%lld ",dis[i]);
	}
	return 0;
} 

5.SPFA(O(km))(慎用)

#include<stdio.h>
#include<algorithm>
#include<queue>
using namespace std;
struct rec{
	int e,d,nex;
}a[500010];
int n,m,s;
int cnt[100010];//判断负环
/*struct queue{
	int head=1,tail=0;
	int z[1000010];
	void push(int x){
		z[++tail]=x;
	} 
	void pop(){
		head++;
	}
	bool empty(){
		if (tail-head<0) return false;
		else return true;
	}
	int size(){
		return tail-head+1;
	}
	int front(){
		return z[head];
	}
};*/
queue<int>q;
int en,first[100010];
bool vis[100010];
long long dis[100010];
void add(int x,int y,int z){
	en++;
	a[en].d=z;
	a[en].e=y;
	a[en].nex=first[x];
	first[x]=en;
}
long long f(int x,int y){
	if (y==0) return 1;
	long long v=f(x,y>>1);
	v=v*v;
	if (y&1==1){
		v=v*x;
	}
	return v;
}
void spfa(int st){
	for (int i=1;i<=n;i++){
		dis[i]=f(2,31)-1;
	}
	dis[st]=0;
	vis[st]=true;
	q.push(st);
	while (!q.empty()){
		int p=q.front();
		q.pop();
		vis[p]=false;
		for (int i=first[p];i!=0;i=a[i].nex){
			int e=a[i].e;
			int d=a[i].d;
			if (dis[e]>dis[p]+d){
				dis[e]=dis[p]+d;
				if (vis[e]==false){
					vis[e]=true;
					//第一种:cnt[e]++; if (cnt[e]>=n)  return 0;
					//第二种:cnt[e]=cnt[p]+1; if (cnt[e]>=n) return 0;
  				    q.push(e);
				}
			}
		}
	}
}
int main(){
	scanf("%d%d%d",&n,&m,&s);
	for (int i=1;i<=m;i++){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
	}
	spfa(s);
	for (int i=1;i<=n;i++){
		printf("%lld ",dis[i]);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值