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,保证观景点两两之间不会有多条游步道连接。
思路分析
这道题本质上是一个无向图上的最长路径问题,且路径中不能重复访问节点,即寻找无重复节点的最长简单路径)。由于 ,我们可以用 DFS回溯 来遍历所有可能的路径,找出总长度最大的一条。
step1:建图
用邻接矩阵或邻接表存图,这里节点数 ,邻接矩阵很方便。
step2:搜索所有简单路径
从每个节点出发,DFS 遍历所有未访问过的相邻节点,记录当前路径长度,更新最大长度。
step3:注意
-
可以从任意节点开始,任意节点结束,所以要对每个节点作为起点做一次 DFS。
-
不需要回到起点,因此只需要在 DFS 过程中记录路径长度最大值。
step4:时间复杂度
最坏情况是搜索所有简单路径,但节点只有 个,且每个节点的度数有限(
),所以可行。
代码实现
#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数组用来避免重复访问节点,回溯时要恢复。

被折叠的 条评论
为什么被折叠?



