题目源自于9oj编号1545。
题目:已知一个无向带权图,求最小整数k。使仅使用权值小于等于k的边,节点1可以与节点n连通。
即,在图中寻找到一条1结点~n结点的路径,并且路径上的所有权值的最大值最小。
思路:
1、寻路:图的BFS或者DFS
2、满足条件:路径上的最大权值最小
一种方法:把每条能够到达的路径找到,且记录下这条路径上的最大权值。
另一种方法:每次设定一个权值上限,找这个权值上限以内的路径。不断尝试这个权值上限,直到找到最小的权值上限。
第一种方法的难处在要在寻路的过程中记录最大权值。
第二种的缺点在于需要对权值上限作循环测试,但是容易实现。
实现:这里使用的是第二种方法。
这里我主要是学习如何快速构建图和图的BFS,BFS如何用来寻路。
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAX = 100000;
vector< pair<int ,int> > e[MAX]; //图的邻接表
bool visited[MAX];
queue<int> q; //为了节省空间,公用一个队列,但是每次BFS记得清空一下。
//find a way from s to t with a limit
bool BFS_search(int s, int t, int limit)
{
memset(visited, false, sizeof(bool)*(t+2));
while(!q.empty())
q.pop();
q.push(s);
visited[s] = true;
while(!q.empty())
{
s = q.front();
q.pop();
int i;
for(i=0;i < e[s].size();i++)
{
int v = e[s][i].first;
if(e[s][i].second > limit)
continue;
if(v == t)
return true;
if(visited[v]== false)
{
visited[v] = true;
q.push(v);
}
}
}
return false;
}
int main()
{
int cost[MAX];
int n, m;
int c, i;
int a, b, d;
while(scanf("%d %d",&n, &m)!=EOF)
{
if(n == 1)
{
printf("0\n");
continue;
}
for(i=1;i<=n;i++)
e[i].clear();
c = 0;
for(i=0;i<m;i++)
{
scanf("%d %d %d", &a, &b, &d);
//加入,这里是无向图
e[a].push_back(make_pair(b, d));
e[b].push_back(make_pair(a, d));
cost[c++] = d;
}
//将所有边的权值排序,去重,得到一个边的权值范围。
sort(cost, cost+c);
c = unique(cost, cost+c) - cost;
//二分查找 寻找最短的一个limit
int ans = -1;
int low=0, high=c-1;
int mid;
while(low<=high)
{
mid = (low+high)>>1;
if(BFS_search(1, n ,cost[mid]))
{
ans = cost[mid];
high = mid -1;
}
else
{
low = mid + 1;
}
}
printf("%d\n", ans);
}
return 1;
}
启发:
图的好多问题解决都可以依靠基础的BFS和DFS来做。可能直观想到的方法我事先不了,但是遇到图问题,首先联系图的BFS/DFS,有想到的可行的方法,是非常重要的。

本文探讨了使用BFS算法解决在无向带权图中找到从节点1到节点n的路径问题,该路径上的最大权重最小。通过构建图和优化路径搜索过程,实现了一个高效的算法来解决此问题。
1093

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



