ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

8.7 浅析图论最短路算法

2021-08-07 19:04:35  阅读:185  来源: 互联网

标签:图论 val 8.7 int tot Maxn include 浅析 dis


个人比较喜欢,dijkstra和spfa

首先,存图方式有很多,个人喜欢链式前向星线性存图

flyod:

这个算法的复杂度是O(n^3),在竞赛中,一般超过一亿的算法就要谨慎,所以,这个可以在n<500的时候用。

1 注意判断重边。

2 注意赋值f[i][i]=0。

3 使用时注意条件。

if(dp[i][k]!=1e9&&dp[k][j]!=1e9)不加这一句的话会莫名其妙出错

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long u,v,w,n,m;
long long dp[1505][1505];
int main()
{
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			dp[i][j]=1e9;
		}
	}
	for(int i=1;i<=n;i++) dp[i][i]=0;
	for(int i=1;i<=m;i++)
	{
		scanf("%lld%lld%lld",&u,&v,&w);
		dp[u][v]=min(dp[u][v],w);
	}
	for(int k=1;k<=n;k++)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(dp[i][k]!=1e9&&dp[k][j]!=1e9)
				dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
			}
		}
	}
	if(dp[1][n]==1e9) printf("-1");
	else printf("%lld",dp[1][n]);
	
	return 0;
}

 spfa:

不用判断重边

个人认为还是一样的思想,枚举中间节点

注意vis数组表示当前这个点有没有在队列内,如果不在,再进行最短路的查找

有缺点就是容易被卡,俗话说的好“spfa它已经死了”,(主要是因为时间复杂度过高),需要跑很多遍错误的前置答案

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int Maxn=2e3+5;
struct egde{
	int to,next,val;
}e[50*Maxn];
queue<int> q;
int n,m,tot;
int head[Maxn],dis[Maxn];
bool vis[Maxn];
inline void add(int u,int v,int w)
{
	e[++tot].to=v;
	e[tot].next=head[u];
	e[tot].val=w;
	head[u]=tot;
}
inline void spfa(int st)
{
	for(int i=1;i<=n;i++)
	{
		dis[i]=1e9;
	}
	dis[st]=0;vis[st]=1;
	q.push(st);
	while(!q.empty())
	{
		int now=q.front();
		q.pop();vis[now]=0;
		for(int i=head[now];i;i=e[i].next)
		{
			int nx=e[i].to;
			if(dis[nx]>dis[now]+e[i].val)
			{
				dis[nx]=dis[now]+e[i].val;
				if(vis[nx]==0)
				{
					vis[nx]=1;
					q.push(nx);
				}
			}
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1,u,v,w;i<=m;i++)
	{
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
	}
	spfa(1);
	if(dis[n]==1e9) printf("-1");
	else printf("%d",dis[n]);
	
	return 0;
}

dijstra:

不用判断重边,但尤其注意不能有负边,一定注意。

时间复杂度低,主要用贪心的想法,可以用堆优化,还是用上为好

//xian-gaoxinyizhong-崔卓
//T3
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std; 
const int Maxn=5e5;
struct egde{
	int to,val,next;
}e[2*Maxn];
struct node{
	int dis,num;
	friend bool operator <(node x,node y)
	{
		return x.dis<y.dis;
	}
}now;
priority_queue<node> q;
int n,m,tot;
int head[Maxn],dis[Maxn];
bool vis[Maxn];
inline void add(int u,int v,int w)
{
	e[++tot].to=v;
	e[tot].val=w;
	e[tot].next=head[u];
	head[u]=tot;
}
inline void dj()
{
	for(int i=1;i<=n;i++)
	{
		dis[i]=1e9;
	}
	dis[1]=0;
	now.dis=0;now.num=1;
	q.push(now);
	while(!q.empty())
	{
		now=q.top();q.pop();
		if(vis[now.num]==0)
		{
			vis[now.num]=1;
			for(int i=head[now.num];i;i=e[i].next)
			{
				if(dis[e[i].to]>dis[now.num]+e[i].val)
				{
					dis[e[i].to]=dis[now.num]+e[i].val;
					if(vis[e[i].to]==0)
					{
						q.push((node){dis[e[i].to],e[i].to});
					}
				}
			}
		}
	}
	
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1,u,v,w;i<=m;i++)
	{
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
	}
	dj();
	if(dis[n]==-1e9)
	{
		printf("-1");
	}
	else printf("%d ",dis[n]);
	
	return 0;
}
/*
7 7
1 2 1
2 5 1
2 3 1
3 6 1
3 4 1
4 7 1
2 7 1
*/

以上都要注意一个问题,开数组的时候,边和点的大小分开开,要不会炸

标签:图论,val,8.7,int,tot,Maxn,include,浅析,dis
来源: https://blog.csdn.net/qq_55284358/article/details/119490840

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有