P1396 营救DFS+二分 kruskal

Posted jason66661010

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1396 营救DFS+二分 kruskal相关的知识,希望对你有一定的参考价值。

题目

https://www.luogu.com.cn/problem/P1396

 

技术图片

 

 分析

这道题与这道题很相似,只不过那道题需要使用dijkstra判断是否到达,而本题只需要使用DFS来判断

大概思路就是这种最大值中的最小的问题:

先找到题目中用到的拥挤度的最大值以及最小值,然后在这个范围内进行二分搜索,在每一次的搜索中,我们使用dfs看以本次搜索用的拥挤度为最大值看在不超过该值的情况下能否从S点到达T点

能的话就缩小二分搜索的值继续查找,如果不能就把搜索的值改大一点,继续搜索

代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
#define maxn 10003
#define maxm 2*maxn
#define inf 0x3f3f3f3f
struct node
{
    int to;
    int next;
    int dis;
}e[maxm*2];
int cnt = 0,n,m,s,t;
int head[maxn],vis[maxn];
void addedge(int u, int v, int w)
{
    cnt++;
    e[cnt].dis = w;
    e[cnt].to = v;
    e[cnt].next = head[u];
    head[u] = cnt;
}
bool ok = false;
void dfs(int start,int cost)
{

    if (start == t)ok = true;
    vis[start] = 1;
    for (int i = head[start]; i; i = e[i].next)
    {
        int y = e[i].to;
        if (vis[y])continue;
        if (e[i].dis > cost)continue;
        dfs(y,cost);
    }
}

int main()
{
    scanf("%d%d%d%d", &n, &m, &s, &t);
    int maxx = -1;
    int minn = inf;
    for (int i = 1; i <= m; i++)
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        if (maxx < c)maxx = c;
        if (minn > c)minn = c;
        addedge(a, b, c);
        addedge(b, a, c);
    }
    int l = minn, r = maxx;
    int ans = 0;
    while (l <= r)
    {
        memset(vis, 0, sizeof(vis));
        ok = false;
        int mid = (l + r) / 2;
        dfs(s, mid);
        if (ok) { r = mid - 1; ans = mid; }
        else l = mid + 1;
    }
    printf("%d", ans);
}

该题的思路还可以使用kruskal算法,在寻找最小生成树的过程中,一旦发现S点与T点已经连接到了一起,就输出此时的边值,因为在寻找的过程中边值的大小是从小到大排列的

所以最后输出的一定是最大的也就是最大值中的最小(其实是先使用kruskal实现最小,再在最小里找最大)而上面的方法是在保证最大的条件下找最小

代码

#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 20001
#define maxm 2*maxn
#define inf 0x3f3f3f3f
struct node
{
    int from;
    int to;
    int dis;
}e[maxm * 2];
int cnt = 0, n, m, s, t;
int father[maxn];
bool cmp(struct node&a, struct node &b)
{
    return a.dis < b.dis;
}
int find(int x)
{
    if (x == father[x])return x;
    return father[x] = find(father[x]);
}
int kruskal()
{
    sort(e, e + m, cmp);
    for (int i = 0; i < m; i++)
    {
        int tempx = find(e[i].from);
        int tempy = find(e[i].to);
        if (tempx == tempy)continue;
        father[tempx] = tempy;
        if (find(s) == find(t))
        {
            return e[i].dis;
        }
    }
}

int main()
{
    scanf("%d%d%d%d", &n, &m, &s, &t);
    for (int i = 0; i < m; i++)
        scanf("%d%d%d", &e[i].from, &e[i].to, &e[i].dis);
    for (int i = 0; i <= m; i++)
        father[i] = i;
    
    printf("%d", kruskal());

}

 

以上是关于P1396 营救DFS+二分 kruskal的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P1396 营救

P1396 营救

Luogu P1396 营救最小生成树/二分答案/最短路 By celur925

洛谷P1396 营救

洛谷——P1396 营救

luogu P1396营救