洛谷 P1294 高手去散步【无向图最长路】C++搜索回溯

题目传送门【P1294 高手去散步】


P1294 高手去散步

题目描述

鳌头山上有 n 个观景点,观景点两两之间有游步道共 m 条。高手的那个它,不喜欢太刺激的过程,因此那些没有路的观景点高手是不会选择去的。另外,她也不喜欢去同一个观景点一次以上。而高手想让他们在一起的路程最长(观景时它不会理高手),已知高手的穿梭机可以让他们在任意一个观景点出发,也在任意一个观景点结束。

输入格式

第一行,两个用空格隔开的整数 n 、 m. 之后 m 行,为每条游步道的信息:两端观景点编号、长度。

输出格式

一个整数,表示他们最长相伴的路程。

输入输出样例

输入 #1复制

4 6
1 2 10
2 3 20
3 4 30
4 1 40
1 3 50
2 4 60

输出 #1复制

150

说明/提示

对于 100% 的数据:n≤20,m≤50,保证观景点两两之间不会有多条游步道连接。


思路分析

这道题本质上是一个无向图上的最长路径问题,且路径中不能重复访问节点,即寻找无重复节点的最长简单路径)。由于 n\leq 20,我们可以用 DFS回溯 来遍历所有可能的路径,找出总长度最大的一条。

step1:建图

用邻接矩阵或邻接表存图,这里节点数 \leq 20,邻接矩阵很方便。

step2:搜索所有简单路径

从每个节点出发,DFS 遍历所有未访问过的相邻节点,记录当前路径长度,更新最大长度。

step3:注意

  • 可以从任意节点开始,任意节点结束,所以要对每个节点作为起点做一次 DFS。

  • 不需要回到起点,因此只需要在 DFS 过程中记录路径长度最大值。

step4:时间复杂度

最坏情况是搜索所有简单路径,但节点只有 20 个,且每个节点的度数有限(m\leq 50),所以可行。

代码实现

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

int n,m;
int g[25][25];//邻接矩阵,0 表示没有边 
bool vis[25];//结点是否被访问过
int mlen=0;//最长路径长度

void dfs(int u,int len) {
	//从 u 出发,当前路径长度为 len
	vis[u]=true;
	mlen=max(mlen,len);//更新最大程度
	
	for(int v=1;v<=n;v++) {
		if(g[u][v]>0&&!vis[v])
			dfs(v,len+g[u][v]);
	}
	vis[u]=false;//回溯
}

int main() {
	cin>>n>>m;
	memset(g,0,sizeof(g));
	
	for(int i=0;i<m;i++) {
		int x,y,l;
		cin>>x>>y>>l;
		g[x][y]=l; g[y][x]=l;
	}
	
	for(int s=1;s<=n;s++) {
		//从每个结点作为起点开始 DFS
		memset(vis,0,sizeof(vis));
		dfs(s,0);
	}
	cout<<mlen;
	return 0;
}
  • DFS 中 visited 数组用来避免重复访问节点,回溯时要恢复。

学习资料

DFS(搜索)- OI Wiki

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值