Codeforces 553D Nudist Beach(图论,贪心)

 

Solution:

      假设已经选了所有的点。

   如果从中删掉一个点,那么其它所有点的分值只可能减少或者不变。

       如果要使若干步删除后最小的分值变大,那么删掉的点集中肯定要包含当前分值最小的点。

       所以每次删掉一个点都记录一次最大值。取最大的情况输出就好。

 

#include <bits/stdc++.h>

using namespace std;



const int N = 100009;



vector<int> E[N], out;

set<pair<double, int>> s;

int deg[N], vis[N], dg[N];

int n, m, k;



int main()

{

    ios::sync_with_stdio ( 0 );

    cin >> n >> m >> k;



    for ( int i = 1, x; i <= k; ++i ) {

        cin >> x;

        vis[x] = 1;

    }



    for ( int i = 1, u, v; i <= m; ++i ) {

        cin >> u >> v;

        E[u].push_back ( v ), ++deg[u];

        if ( !vis[v] ) ++dg[u];

        E[v].push_back ( u ), ++deg[v];

        if ( !vis[u] ) ++dg[v];

    }



    for ( int i = 1; i <= n; ++i ) {

        if (!vis[i])

            s.insert ( make_pair ( 1.*dg[i] / deg[i], i ) );

    }



    double ans = -1;

    while (!s.empty() ) {

        auto it = *s.begin();

        if (it.first > ans) {

            ans=it.first;

            out.clear();

            for (auto &i : s) {

                out.push_back (i.second);

            }

        }

        s.erase (s.begin() );

        vis[it.second] = 1;

        for (auto &i : E[it.second]) {

            if (!vis[i]) {

                s.erase (make_pair (1.*dg[i] / deg[i], i) );

                --dg[i];

                s.insert (make_pair (1.*dg[i] / deg[i], i) );

            }

        }

    }



    cout << out.size() << endl;

    for (auto &i : out) {

        cout << i << " ";

    }

}
View Code

 

你可能感兴趣的:(codeforces)