【算法】并查集刷题总结

目录

P1396 营救
题目描述
“咚咚咚……”“查水表!”原来是查水表来了,现在哪里找这么热心上门的查表员啊!小明感动的热泪盈眶,开起了门……
妈妈下班回家,街坊邻居说小明被一群陌生人强行押上了警车!妈妈丰富的经验告诉她小明被带到了t区,而自己在s区。
该市有m条大道连接n个区,一条大道将两个区相连接,每个大道有一个拥挤度。小明的妈妈虽然很着急,但是不愿意拥挤的人潮冲乱了她优雅的步伐。所以请你帮她规划一条从s至t的路线,使得经过道路的拥挤度最大值最小。
输入格式
第一行四个数字n,m,s,t。
接下来m行,每行三个数字,分别表示两个区和拥挤度。
(有可能两个区之间有多条大道相连。)
输出格式
输出题目要求的拥挤度。
输入
3 3 1 3
1 2 2
2 3 1
1 3 3

输出
2
思路:题目求经过道路的拥挤度最大值最小。我们可以考虑二分。我们就分距离。L = (边的最小值) R = (边的最大值)check可以这样写:如果用权值小于等于mid的边能到达t,return 1;else return 0;将权值小于等于mid的边的量个点合并起来,最后再用并查集判一下,看是否可以达到目的地

#include
#include
#include
#include
#include
#include
#include
#define debug cout<<"ok"<
typedef long long ll;
const int maxn=1e5+500;
const int mod=1e9+7;
using namespace std;
int n,m,s,t,f[maxn],a[maxn],vis[maxn],b[maxn],ans,l=mod,r,mid;//l取一极大值用于查找最小值
inline int finds(int x)
{
     
    return f[x]==x?x:f[x]=finds(f[x]);//查
}
inline void join(int aa ,int bb)//并
{
     
    if(finds(aa)!=finds(bb));
    f[finds(aa)]=f[finds(bb)];//注意这道题判别的时候是判父节点是否都相等所以join的时候应该并父节点
}
inline bool judge(int x,int y)//判
{
     
    return finds(x)==finds(y);
}
inline bool check(int x)//二分中的check
{
     
    for(int i=1;i<=n;i++)//每一次都必须重新赋值
        f[i]=i;
    for(int i=1;i<=m;i++)
        if(vis[i]<=x)//二分查最小值把<=该值的路全部用上看能否符合题意(到达终点)若能则该值减小再判能否成立
        join(a[i],b[i]);//在此方案中把涉及到的全部连起来
    return judge(s,t);//判断此方案能否从起点走到终点
}
int main()
{
     
    ios::sync_with_stdio(false);//cin加速
    cin>>n>>m>>s>>t;
    for(int i=1;i<=m;i++)
        cin>>a[i]>>b[i]>>vis[i],l=min(l,vis[i]),r=max(r,vis[i]);
    while(l<=r)//二分查找
    {
     
        mid=(l+r)>>1;
        if(check(mid))ans=mid,r=mid-1;//每一次都更新一次ans;
        else l=mid+1;
    }
    cout<<ans<<endl;
    return 0;
}

注:如果您通过本文,有(qi)用(guai)的知识增加了,请您点个赞再离开,如果不嫌弃的话,点个关注再走吧 ! 当然,也非常欢迎您能在讨论区指出此文的不足处,作者会及时对文章加以修正 !如果有任何问题,欢迎评论,非常乐意为您解答!( •̀ ω •́ )✧

你可能感兴趣的:(【算法总结】合集,#,并查集)