zoukankan      html  css  js  c++  java
  • hiho一下 第三十八周 二分答案

      题目链接:http://hihocoder.com/contest/hiho38/problem/1 ,挺难想的解题思路,好题。


    按照提示的算法来:

    我们需要找什么?
      在这个题目中我们需要找的是路径最长边。比如存在一条路径{1, p[1], p[2], ... , p[j], T}, p = {p[1],p[2],...,p[j]] }, j < K,我们需要找的为 D(P) = Max{w(1, p[1]), w(p[j], T), Max{w(p[i], p[i+1]) | 1 <= i < j} }。则这道题的结果为找出所有从1到T的路径P',求的Min{D(P')}。由于给定的图存在环,所以要枚举出所有1到T的路径是很难的,因此我们需要换个角度去思考这个问题。

    这道题结果有什么特殊性?  

      不妨假设答案为j,如果舰队满足j以上的索敌值,那么一定存在至少一条路径可以从1到T,并且路径数量小于K。如果舰队索敌值小于j,则在K条路径的条件下一定无法从1到T。否则j就不是最小值了。

    则对于索敌值满足这样一个关系:

    可以看出,j值刚好是是否存在路径的一个分界线。如果我们枚举一个j':

    • j'<j,无法到达boss点

    • j'>=j,一定可以到达boss点

    则如何快速的找到这个分界线j,就是解决这道题目的关键。

    不妨设f(x) = true(索敌值为x时,可以达到boss点), false(索敌值为x时,不能达到boss点)
    二分枚举,设定枚举区间[L,R],满足f(L)=false, f(R)=true。每次取中间值Mid=(L+R)/2,若f(Mid)=true,令R=Mid;否则令L=Mid。
    当L+1=R时,可以知道R即为我们需要寻找的j。

    关于f(x)的求法:

      可以用BFS来判断,这里要用一个数组deep[]记录每个结点的深度信息。所以访问到一个结点时,判断该结点是否能加入队列的条件有三个:该点未访问;到达该点后路径长度不超过k(用deep[]数组来判断);当前的索敌值x不小于这条边的索敌值w。

      如果能在限制条件下到达boss的位置就返回true,否则返回false。

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <queue>
    #include <cmath>
    #include <string>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define LL __int64
    #define eps 1e-8
    #define INF 1000005
    const int maxn = 100000 + 5;
    struct Edge {    
        int v , w;
    };
    vector <Edge> e[maxn];        //邻接表来表示图
    int vis[maxn] , deep[maxn];
    bool check(int start , int j , int k , int end) 
    {                //用BFS来判断,起始点为start,j为最小索敌值,k为限制路径长度
        memset(vis , 0 , sizeof(vis));
        queue <int> que;
        que.push(start);
        vis[start] = 1;
        deep[start] = 0;
        while(!que.empty()) {
            int u = que.front();
            que.pop();
            for(int i = 0 ; i < e[u].size() ; i++) {
                int v = e[u][i].v;
                int w = e[u][i].w;
                if(!vis[v] && deep[u] < k && j >= w) {    //三个条件    
                    if(v == end)
                        return true;
                    vis[v] = 1;
                    deep[v] = deep[u] + 1;
                    que.push(v);
                }
            }
        }
        return false;
    }
    int binary_search(int l , int r , int k , int t)
    {                    //二分答案,区间为[l , r],限制路径长度k,终点为t
        int m = (l + r) >> 1;
        while(l + 1 != r) {
            if(check(1 , m , k , t))
                r = m;
            else
                l = m;
            m = (l + r) >> 1;
        }
        return r;
    }
    int main()
    {
        int n , m , k , t;
        scanf("%d %d %d %d" , &n , &m , &k , &t);
        while(m--) {
            int u , v , w;
            scanf("%d %d %d" , &u , &v , &w);
            Edge tmp = {v , w};
            e[u].push_back(tmp);
            tmp.v = u;
            e[v].push_back(tmp);
        }
        int res = binary_search(0 , INF , k , t);
        printf("%d
    " , res);
        return 0;
    }
  • 相关阅读:
    PHP中功能强大却少使用的函数
    php 判断美国zip code
    php 操作 MySQL 中的Blob类型
    THINKPHP 多域名 MEMCACHE方式共享SESSION数据
    phpQuery—基于jQuery的PHP实现
    Error calling method on NPObject!
    国外共享软件热门上载站点
    你留意过自己的父母吗?
    域名LOGO产生器 (全智能)
    想要创业者须知 企业注册商标6大步
  • 原文地址:https://www.cnblogs.com/H-Vking/p/4365411.html
Copyright © 2011-2022 走看看