题目背景
“咚咚咚……”“查水表!”原来是查水表来了,现在哪里找这么热心上门的查表员啊!小明感动的热泪盈眶,开起了门……
题目描述
妈妈下班回家,街坊邻居说小明被一群陌生人强行押上了警车!妈妈丰富的经验告诉她小明被带到了 t 区,而自己在 s 区。
该市有 m 条大道连接 n 个区,一条大道将两个区相连接,每个大道有一个拥挤度。小明的妈妈虽然很着急,但是不愿意拥挤的人潮冲乱了她优雅的步伐。所以请你帮她规划一条从 s 至 t 的路线,使得经过道路的拥挤度最大值最小。
输入格式
第一行有四个用空格隔开的 n,m,s,t,其含义见【题目描述】。
接下来 m 行,每行三个整数 u,v,w表示有一条大道连接区 u 和区 v,且拥挤度为 w。
两个区之间可能存在多条大道。
输出格式
输出一行一个整数,代表最大的拥挤度。
输入输出样例
输入 #1
3 3 1 3 1 2 2 2 3 1 1 3 3
输出 #1
2
说明/提示
数据规模与约定
- 对于 30% 的数据,保证 n≤10。
- 对于 60% 的数据,保证 n≤100。
- 对于 100% 的数据,保证 1≤n≤10^4 1≤m≤2×10^4 w≤10^4,1≤s,t≤n。且从 s 出发一定能到达 t 区。
样例输入输出 1 解释
小明的妈妈要从 1号点去 3 号点,最优路线为 1->2->3。
解析:
题型:求最大值中的最小值。
这里有一个类似的题:https://blog.csdn.net/qq_36915686/article/details/105069393
思路:
先说一下什么叫做最大值中的最小值。
假设从s--->t的路径有P1,P2,...,Pn
对于Pi (1=<i<=n),这条路径来说:
假设有m条道路,而且这m条道路的拥挤度分别为:C1,C2,...,Cn
令Wi = max(C1,C2,...,Cn)
则我们的答案就是:min(W1,W2,...,Wn)
也就是我们手中拿着一个拥挤度C,可以从s走到t,而且s--->t这条路径上每条道路上的拥挤度都小于C
我们用kruskal算法,我https://blog.csdn.net/qq_36915686/article/details/105069393这篇博客讲的是一个类似的题,用的是Dijkstra算法+二分选择。但是觉得还是kruskal算法好用啊。
答案就是当s和t连通时,加入的最后一条边的拥挤度。
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<map>
using namespace std;
const int MAXN = 10002;
const int INF = 999999;
struct Edge{
int u;
int v;
int w;
Edge(int u,int v,int w){
this->u = u;
this->v = v;
this->w = w;
}
// bool operator<(const Edge &edge) const {
// return this->w < edge.w;
// }
};
vector<Edge> edges; //存储边
int father[MAXN]; //祖先数组
//初始化祖先数组
void initFather(int n){
for(int i=0;i<=n;i++){
father[i] = i;
}
}
//找到x的祖先
int findFather(int x){
int z = x;
while(x != father[x]){
x = father[x];
}
int temp;
while(z != father[z]){
temp = z;
z = father[z];
father[temp] = x;
}
return x;
}
/*
**判断x和y的祖先是不是同一个人
**如果不是同一个人,说明x和y在不同的连通块中
**即x和y还不连通,那就把y的祖先设置为x,这样x和y就在同一个连通块中了
*/
bool unionFather(int x,int y){
int fx = findFather(x); //找x的祖先
int fy = findFather(y); //找y的祖先
if(fx != fy){ //祖先不同
father[fy] = fx; //把fy的祖先设置为fx,这样x和y就有同一个祖先了:fx
return true;
}
return false;
}
//用来排序
bool cmp(const Edge &edge1,const Edge &edge2){
return edge1.w < edge2.w;
}
int kruskal(int n,int s,int t){
initFather(n);
sort(edges.begin(),edges.end(),cmp);
for(int i=0;i<edges.size();i++){
Edge edge = edges[i];
int u = edge.u;
int v = edge.v;
if(unionFather(u,v)){
//每将一条边加入,就检查s和t的连通性
if(findFather(s) == findFather(t)){ //判断s和t是否连通
return edge.w; //如果连通,返回刚才加入的那条边的权重
}
}
}
return -1;
}
int main(){
int n,m,s,t;
int u,v,w;
cin>>n>>m>>s>>t;
while(m--){
cin>>u>>v>>w;
edges.push_back(Edge(u,v,w));
}
cout<<kruskal(n,s,t)<<endl;
return 0;
}