图算法之最短路二

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

 

一、Dijkstra

这是一个非常常用来处理正权图的一个算法,一般不用来处理有负权的图0。可以使用链式前向星来优化。

1、时间复杂度

n的平方;

2.算法模板

void DJ(int s)
{
	for(int i=1;i<=n;i++) dis[i]=INF,vis[i] = false;
	dis[s]=0;
	
	for(int i=1;i<=n;i++){
		int t=-1;
		for(int j=1;j<=n;j++)
			if(!vis[j]&&(t==-1||dis[j]<dis[t]))
				t=j;
		if(t==-1) return ;
		vis[t] = true;
		
		for(int j=1;j<=n;j++){
			dis[j] = min(dis[j],dis[t]+f[t][j]);
		}
	}
}

3.DJ的堆优化

void DJ(int s)
{
	for(int i=1;i<=n;i++) dis[i]=INF,vis[i] = false;
	dis[s]=0;
	
	priority_queue<PII,vector<PII>,greater<PII> > q;//建立一个小顶堆
	q.push({0,s});
	while(!q.empty())
	{
		int t = q.top().second;
		q.pop();
		if(vis[t]) continue;
		vis[t] =true;
		
		for(int i=0,l=E[t].size();i<l;i++)
		{
			int j = E[t][i].first,w = E[t][i].second;
			if(dis[j]>dis[t]+w)
			{
				dis[j]=dis[t]+w;
				q.push({dis[j],j});
			}			
		}
	}
}

二.关于最短路的一些例题

https://ac.nowcoder.com/acm/contest/27274/E


 这是一道很简单的一道最短路的模拟题,主要是练习模板,这道题数据给的很水,每个个方法都可以解决这道题。我就只用一个方法来解决,我用的DJ的堆优化。

#include<bits/stdc++.h>
using namespace std;

#define PII pair<int,int>

const int INF = 0x3f3f3f3f;
const int N = 1e3+10;

int n,m,s,t;
int dis[N];
bool vis[N];
int f[N][N];
vector <PII> E[N];

void DJ(int s)
{
	for(int i=1;i<=n;i++) dis[i]=INF,vis[i] = false;
	dis[s]=0;

	priority_queue<PII,vector<PII>,greater<PII> > q;
	q.push({0,s});
	while(!q.empty())
	{
		
		int t = q.top().second;
		q.pop();
		if(vis[t]) continue;
		vis[t] =true;

		for(int i=0,l=E[t].size();i<l;i++)
		{
			int j = E[t][i].first,w = E[t][i].second;
			if(dis[j]>dis[t]+w)
			{
				dis[j]=dis[t]+w;
				q.push({dis[j],j});
			//	cout<<1<<endl;
			}
		}
	}
}


int main()
{
	cin>>n>>m>>s>>t;
	while(m--)
	{
		int u,v,w;
		cin>>u>>v>>w;
		E[u].push_back({v,w});
		E[v].push_back({u,w});
	}
	DJ(s);
	if(dis[t]>INF/2) cout<<"-1"<<endl;
	else cout<<dis[t]<<endl;

	return 0;
}

 题目详情 - 单源最短路 - 追梦算法网 (mangata.ltd)

 

这道题题也是也是比较基础的一道最短路,但是要注意数据,防止t了,我用的bellam_ford来写的。

#include<bits/stdc++.h>
using namespace std;

#define PII pair<int,int>

const int INF = 0x3f3f3f3f;
const int N = 1e3+10;

int n,m,s,t;
int dis[N];
bool vis[N];
int f[N][N];

struct ma
{
	int u,v,w;
};

vector <ma> E;

void bellman_ford(int s)
{
	for(int i=1;i<=n;i++) dis[i] = INF;
	dis[s] = 0;
	for(int i = 1;i<=n;i++)
	{
		for(int j =0;j< 2 * m;j++)
		{
			int v =E[j].v,u = E[j].u,w=E[j].w;
			if(dis[v] > dis[u]+w) dis [v] = dis[u]+w;
		}
	}
}


int main()
{
	cin>>n>>m>>s>>t;
	int tt = m;
	
	while(tt--)
	{
		int u,v,w;
		cin>>u>>v>>w;
		E.push_back({u,v,w});
		E.push_back({v,u,w});
	}
	bellman_ford(s);

	 cout<<dis[t]<<endl;

	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cocolaret

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值