最短路

最少转机
p142
就是求权值为1的无向图 从一个点到另一个点最短路径

我写了两种做法
还有3种做法后面补充

  1. dfs版
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int n,m,startx,endx;
int a,b,minn=99999999;
int e[1000][1000],vis[1000];
void dfs(int cur,int sum)//cur代表正在访问点的编号 sum表示路径总和
{
	if(sum>minn) return ;//当路径大于最优解 (剪枝)
	if(cur==endx){//到达终点
		minn=min(minn,sum);//更新最小值
		return ;
	}
	for(int i=1;i<=n;i++){
		if(e[cur][i]==1&&vis[i]==0)//判断
		{
			vis[i]=1;//标记
			dfs(i,sum+1);//继续深搜
			vis[i]=0;//回溯
			//因为有多种走法 所以要回溯 为下一次
		}
	}
}
int main()
{
	cin>>n>>m>>startx>>endx;//输入

	//邻接矩阵存图
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(i==j) e[i][j]==0;//自己到自己为路径为0
			else e[i][j]=minn;//其他赋值为正无穷 就是无法走
	for(int i=1;i<=m;i++)
	{
		cin>>a>>b;//输入两端点的路
		e[a][b]=e[b][a]=1;//无向图
 	}
	vis[startx]=1;//一定要标记 因为是从startx开始的
	dfs(startx,0);
	cout<<minn<<endl;//最后输出
	return 0;
}
  1. bfs版
    队列模拟 废话
    本蒟蒻还不会stl 只好手写
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
struct x{
	int sum,node;//sum存路径总和 node表示正在访问点的编号
}q[100000];
int n,m,startx,endx;
int a,b,minn=99999999;
int e[1000][1000],vis[1000];
int head,tail;
void init()
{
	cin>>n>>m>>startx>>endx;
	//邻接矩存图
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
		 if(i==j) e[i][j]=0;//不重负说
		 else e[i][j]=minn;
	
	for(int i=1;i<=m;i++)
	{
		cin>>a>>b;
		e[a][b]=e[b][a]=1;
		//再次强调这是无向图
	}
}
int main()
{
	int flag=0;
	init();
	head=1,tail=1;//初始化队列为空
	q[tail].node=startx;//第一个元素入队
	q[tail].sum=0;//刚开始为0
	vis[startx]=1;//标记已经入队元素
	tail++;//更新尾指针
	while(head<tail)//当队列不为空
	{
		int cur=q[head].node;//当前队列的首城市编号
		for(int i=1;i<=n;i++)
		{
			if(e[cur][i]==1&&vis[i]==0)//判断
			{
				q[tail].node=i;//更新入队
				vis[i]=1;//标记
				q[tail].sum=q[head].sum+1;//为首城市转机次数+1
				tail++;//更新尾指针
			}
			if(q[tail-1].node==endx)//当到达终点
			//一定要注意 tail是一直指向下一个元素的 所以要-1
			{
				flag=1;
				break;
			}
		}
		if(flag) break;
		head++;//别忘了出队了
	}
	cout<<q[tail-1].sum<<endl;
	//注意tail是指向队尾元素的下一个 千万记住 所以-1
	return 0;
}

这里一定要注意一点 只有当每条边权值相等时 才可以用bfs
如题中 每条边权值为1
如果权值不相等 bfs就不能保证在扩展时得到最优解 就不正确了

  1. Floyd

#include<iostream>
#include<cstdio>
using namespace std;
int n,m,sx,ex,e[1000][1000],minn=9999999,a,b;
int main()
{
	//邻接矩阵存图法
	//这个非常重要 到时候dlj也要用到 前面dfs bfs也用到了 
	scanf("%d %d %d %d",&n,&m,&sx,&ex);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(i==j) e[i][j]=0;
			else e[i][j]=minn;
		}
	}
	
	for(int i=1;i<=m;i++)
	{
		cin>>a>>b;
		e[a][b]=e[b][a]=1;
	}
	
	//floyd核心代码 
	for(int k=1;k<=n;k++)
	{
		for(int i=1;i<+n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(e[i][j]>e[i][k]+e[k][j]) e[i][j]=e[i][k]+e[k][j];//dp过程
				//这个的思想是 枚举一个中间点 依次带入(i,j)去试
				//然后慢慢更新 时间复杂度是n^3 
			}
		}
	}
	cout<<e[sx][ex]<<endl;
	return 0; 
}```

dijkstra做法

#include
#include
using namespace std;
int n,m,e[1000][1000],dis[1000],a,b,vis[10000],u,minn,inf=9999999;
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)

  for(int j=1;j<=n;j++)
    if(i==j) e[i][j]=0;
    else e[i][j]=inf;
    
for(int i=1;i<=m;i++)
{
	cin>>a>>b;
	e[a][b]=e[b][a]=1;
}

for(int i=1;i<=n;i++) dis[i]=e[1][i];
vis[1]=1;

for(int i=1;i<=n-1;i++)
{
	minn=inf;
	//更新最小值
	for(int j=2;j<=n;j++)
	{
		if(vis[j]==0&&dis[j]<minn){minn=dis[j];u=j;}
	}
	vis[u]=1;
	//核心代码
	for(int v=1;v<=n;v++)
	{
		dis[v]=min(dis[v],dis[u]+e[u][v]);
	}
} 
cout<<dis[n]<<endl;
return 0;

}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值