zoukankan      html  css  js  c++  java
  • 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());
    
    }
  • 相关阅读:
    初识Kafka
    初学Linux (Linux_note)
    Zookeeper_ACL
    Zookeeper简单配置
    getWindow().setFlags
    设置session失效时间
    Android开发者必知的5个开源库
    oracle A用户访问B用户的表aa
    oracle 根据约束名查表名
    java ftp上载下传 遇到的问题
  • 原文地址:https://www.cnblogs.com/Jason66661010/p/13196095.html
Copyright © 2011-2022 走看看