SSL 1763 观光旅游(floyd,dijkstra)

本文介绍两种寻找图中最小环的方法:Floyd算法和枚举结合Dijkstra算法。通过具体实例展示了算法实现步骤,并提供了C++代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

找一个最小环
这里写图片描述
1-2-5-3-1 16+15+20+10=61


分析(1)

这道题用floyd,找最小值
伪代码

for (int k=1;k<=n;k++){
		for (int i=1;i<k-1;i++)
		for (int j=i+1;j<k;j++)
		ans=min(ans,dis[i][j]+a[i][k]+a[k][j]);//寻找最小环
		for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++)
		if (dis[i][j]>dis[i][k]+dis[k][j]) dis[i][j]=dis[i][k]+dis[k][j];//floyd正常过程
	}

floyd代码(1)

#include <cstdio>
#include <cctype>
#include <algorithm>
#include <cstring>
using namespace std;
int n,m,a[101][101],x,y,ans=2147483647,dis[101][101];
int in(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
int main(){
	n=in(); m=in(); memset(dis,127/3,sizeof(dis)); memset(a,127/3,sizeof(a));
	for (int i=1;i<=m;i++) a[x=in()][y=in()]=a[y][x]=dis[x][y]=dis[y][x]=in();
	ans=dis[0][0];
	for (int k=1;k<=n;k++){
		for (int i=1;i<n;i++)
		for (int j=i+1;j<=n;j++)
		ans=min(ans,dis[i][j]+a[i][k]+a[k][j]);
		for (int i=1;i<=n;i++)
		for (int j=1;j<=n;j++)
		if (dis[i][j]>dis[i][k]+dis[k][j]) dis[i][j]=dis[i][k]+dis[k][j];
	}
	if (ans!=dis[0][0]) printf("%d",ans);//没找到
	else puts("No solution");
	return 0;
}

分析(2)

使用枚举+dijkstra的方法
删掉一条边,求这条边的一个点到另一个点的最短路径,最短路径加上这条边的权值为答案。
这里写图片描述
16+15+20+10=61


dijkstra代码

#include <cstdio>
#include <cctype>
#include <cstring>
using namespace std;
int n,m,x,y,mins; bool v[101]; 
int low[101],a[101][101];
int in(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
int main(){
	n=in(); m=in(); memset(a,127/3,sizeof(a)); mins=a[0][0];
	for (int i=1;i<=m;i++) a[x=in()][y=in()]=a[y][x]=in();
    for (int y=2;y<=n;y++)
    for (int x=1;x<y;x++)
	if (a[x][y]!=a[0][0]){//可以通行
		int t=a[x][y]; a[x][y]=a[y][x]=a[0][0];//删掉
	    for (int i=1;i<=n;i++) low[i]=a[x][i];
		memset(v,0,sizeof(v)); v[x]=1; 
		for (int i=1;i<n;i++){//dijkstra
			int min=a[0][0],k=0;
			for (int j=1;j<=n;j++)
			if (!v[j]&&min>low[j]) min=low[j],k=j;//求最小边
			if (!k) break; v[k]=1;
			for (int j=1;j<=n;j++) if (!v[j]&&low[j]>low[k]+a[k][j]) low[j]=low[k]+a[k][j];//更新
		}
		mins=mins>(low[y]+t)?(low[y]+t):mins; a[x][y]=a[y][x]=t;
    }
    if (mins!=a[0][0]) printf("%d",mins); else puts("No solution");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值