zoukankan      html  css  js  c++  java
  • CF553D Nudist Beach

    题目地址

    这里

    Solution

    一道比较简单的二分

    先分析一下题目性质:任意城市被敌军占领,其周围城市的安全度都会降低(implies)
    我们在选取城市时,应遵循这样一个原则:所有能够被己方控制的城市都应当让己方控制。

    这里的“能够”当然只在二分答案的限制下才有意义。

    那么,解决方法就很简单了。
    利用队列,先将必须被敌军占领(有堡垒)的城市入队,将队列中的城市一个个拿出来更新其周围城市的安全度,如果更新后安全度小于(mid)就将这个城市入队。

    如果最后还有城市未被敌军占领,(l = mid)否则,(r = mid),最终(l)为最大安全度。

    另外,这道题对精度的要求比较高,我设置的精度是(10^{-9})(10^{-8})以上大概就过不了了。

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int MAXN = 1e5 + 10;
    const double eps = 1e-9;
    
    int n,m,k,siz[MAXN];
    int num[MAXN],d[MAXN];//d:某城市周围被敌军占领的城市数量。
    bool vis[MAXN];
    vector<int> e[MAXN];
    queue<int> q;
    
    bool judge(double mid) {
        memset(vis,false,sizeof(vis));
        memset(d,false,sizeof(d));
        for (int i = 1; i <= k; i++) {
            q.push(num[i]);vis[num[i]] = true;
            for (int j = 0; j < siz[num[i]]; j++) {
                d[e[num[i]][j]]++;
            }
        }
        while (!q.empty()) {
            int u = q.front();q.pop();
            int len = e[u].size();
            for (int i = 0; i < len; i++) {
                int v = e[u][i];
                if (vis[v]) continue;
                double nu = ((siz[v] - d[v]) * 1.0 / siz[v]);
                if (nu < mid) {
                    vis[v] = true;
                    for (int j = 0; j < siz[v]; j++) {
                        d[e[v][j]]++;
                    }
                    q.push(v);
                }
            }
        }
        for (int i = 1; i <= n; i++) if (!vis[i]) return true;
        return false;
    }
    
    int main() {
        scanf("%d%d%d",&n,&m,&k);
        for (int i = 1; i <= k; i++) {
            scanf("%d",&num[i]);
        }
        for (int i = 1; i <= m; i++) {
            int u,v;
            scanf("%d%d",&u,&v);
            e[u].push_back(v);
            e[v].push_back(u);
        }
        for (int i = 1; i <= n; i++) siz[i] = e[i].size();
        double l = 0,r = 1.0;
        while (r - l > eps) {
            double mid = (l + r) / 2;
            if (judge(mid)) l = mid;
            else r = mid;
        }
        memset(vis,false,sizeof(vis));
        judge(l);
        int cnt = 0;
        for (int i = 1; i <= n; i++) {
            if (!vis[i]) {
                cnt++;
            }
        }
        cout << cnt << endl;
        for (int i = 1; i <= n; i++) {
            if (!vis[i]) printf("%d ",i);
        }
        return 0;
    }
    
  • 相关阅读:
    Windows2012下安装和配置Oracle BIEE12c
    Windows Oracle 12安装教程
    SpringCloud学习之Ribbon使用(四)
    SpringCloud学习之手把手教你用IDEA搭建入门项目(三)
    SpringCloud学习之手把手教你用IDEA搭建入门项目(二)
    SpringCloud学习之手把手教你用IDEA搭建入门项目(一)
    SpringCloud学习之手把手教你用IDEA搭建入门项目【番外篇】(一)
    SpringCloud学习之大纲总略(大纲篇)
    Websocket @serverendpoint 404
    XMLHttpRequest status为0
  • 原文地址:https://www.cnblogs.com/kjd123456/p/14378700.html
Copyright © 2011-2022 走看看