• noip模拟赛 radius


    分析:这道题实在是不好想,一个可以骗分的想法是假定要求的那个点在中心点上,可以骗得不少分.但是在边上的点要怎么确定呢?理论复杂度O(﹢无穷).答案一定是和端点有关的,涉及到最大值最小,考虑二分最大值,关键就是怎么check.如果有一条边x,还有一个点y,把y到x上的点的距离>mid的点给标记上,这样就会形成许多个区间,判断一下x是否被这些区间给完全覆盖住了,如果没有被完全覆盖住,证明这个最大值可以更小.思路非常奇妙,具体实现细节可以参看代码:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 210, maxm = 40010;
    
    int n, m, a[maxn][maxn], head[maxn], to[maxm],ans,len,top,nextt[maxm],w[maxm], tot = 1;
    struct node
    {
        int x, y, z;
    }e[20000];
    
    struct node2
    {
        int first, second;
    }e2[20000];
    
    void add(int x, int y, int z)
    {
        w[tot] = z;
        to[tot] = y;
        nextt[tot] = head[x];
        head[x] = tot++;
    }
    
    void floyd()
    {
        for (int k = 1; k <= n; k++)
            for (int i = 1; i <= n; i++)
                for (int j = 1; j <= n; j++)
                    if (a[i][j] > a[i][k] + a[k][j])
                        a[i][j] = a[i][k] + a[k][j];
    }
    
    void add2(int x, int y)
    {
        e2[++top].first = x;
        e2[top].second = y;
    }
    
    bool cmp(node2 a, node2 b)
    {
        if (a.first == b.first)
            return a.second < b.second;
        return a.first < b.first;
    }
    
    bool can()
    {
        int x = 0;
        sort(e2 + 1, e2 + 1 + top,cmp); 
        for (int i = 1; i <= top; i++)
        {
            if (x < e2[i].first)
                return false;
            if (x > e2[i].second)
                continue;
            x = e2[i].second + 1;
        }
        if (x > len)
            return true;
        return false;
    }
    
    bool check(int p)
    {
        bool flag = false;
        for (int i = 1; i <= m; i++)
        {
            top = 0;
            len = e[i].z;
            for (int j = 1; j <= n; j++)
            {
                int x = p - a[e[i].x][j];
                int y = p - a[e[i].y][j];
                if (x < 0 && y < 0)
                {
                    add2(0, e[i].z);
                    break;
                }
                if (x >= e[i].z || y >= e[i].z)
                    continue;
                if (x + y >= e[i].z)
                    continue;
                add2(max(0, x + 1), min(e[i].z, e[i].z - y - 1));
            }
            if (!can())
                flag = 1;
            if (flag)
                break;
        }
        if (flag)
            return true;
        return false;
    }
    
    int main()
    {
        memset(a, 127 / 3, sizeof(a)); 
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= m; i++)
        {
            int u, v, z;
            scanf("%d%d%d", &u, &v, &z);
            z *= 2;
            add(u, v, z);
            add(v, u, z);
            e[i].x = u;
            e[i].y = v;
            e[i].z = z;
            a[u][v] = a[v][u] = min(a[u][v], z);
        }
        for (int i = 1; i <= n; i++)
            a[i][i] = 0;
        floyd();
        int l = 0, r = 10000010;
        while (l <= r)
        {
            int mid = (l + r) >> 1;
            if (check(mid))
            {
                ans = mid;
                r = mid - 1;
            }
            else
                l = mid + 1;
        }
        double temp = ans / 2.0;
        printf("%.2lf
    ", temp);
    return 0;
    }
  • 相关阅读:
    js中的同步与异步
    全局刷新 局部刷新
    url的组成
    Linux云自动化运维第十二课
    Linux云自动化运维第十一课
    Linux云自动化运维第十课
    Linux云自动化运维第九课
    Linux云自动化运维第八课
    Linux云自动化运维第七课
    Linux云自动化运维第六课
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7726133.html
Copyright © 2020-2023  润新知