C. Hongcow Builds A Nation 并查集

http://codeforces.com/contest/745/problem/C

把他们并查集后,

其他没有连去government的点,全部放去同一个并查集,然后选择一个节点数最多的government集合,连接过去即可。

至于有多少条边增加,可以暴力判断。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 1e4 + 201;
int fa[maxn];
int tofind(int x) {
    if (fa[x] == x) return x;
    else return fa[x] = tofind(fa[x]);
}
void tomerge(int x, int y) {
    x = tofind(x);
    y = tofind(y);
    if (x != y) fa[y] = x;
}
int tohash[maxn];
bool e[maxn][maxn];
vector<int>gg[maxn];
int cc[maxn];
int id[maxn];
bool vis[maxn];
bool has[maxn];
void work() {
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 1; i <= maxn - 20; ++i) fa[i] = i;
    for (int i = 1; i <= k; ++i) {
        int x;
        scanf("%d", &x);
        tohash[x] = 1;
        cc[i] = x;
    }
    for (int i = 1; i <= m; ++i) {
        int u, v;
        scanf("%d%d", &u, &v);
        e[u][v] = e[v][u] = 1;
        tomerge(u, v);
    }
    for (int i = 1; i <= n; ++i) {
        gg[tofind(i)].push_back(i);
    }
//    for (int i = 1; i <= n; ++i) {
//        for (int j = 0; j < gg[tofind(i)].size(); ++j) {
//            printf("%d ", gg[tofind(i)][j]);
//        }
//        printf("
");
//
//    }
    int lenid = 0;
    for (int i = 1; i <= n; ++i) {
        if (vis[tofind(i)]) continue;
        vis[tofind(i)] = true;
//        cout << "ff" << endl;
        bool flag = false;
        for (int j = 0; j < gg[tofind(i)].size(); ++j) {
            if (tohash[gg[tofind(i)][j]]) {
                flag = true;
                has[tofind(i)] = true;
                break;
            }
        }
        if (!flag) {
            id[++lenid] = tofind(i);
        }
    }
    int togo = n + 1;
    for (int i = 1; i <= lenid; ++i) {
        tomerge(togo, id[i]);
    }
    for (int i = 1; i <= n; ++i) {
        if (has[tofind(i)]) continue;
//        cout << "ff" << endl;
        assert(tofind(i) == togo);
        gg[tofind(i)].push_back(i);
    }
    int ans = 0;
    int mx = -inf;
    memset(vis, 0, sizeof vis);
    for (int i = 1; i <= n; ++i) {
        if (!has[tofind(i)]) continue;
//        cout << "ff" << endl;
        if (vis[tofind(i)]) continue;
        vis[tofind(i)] = true;
        int tt = gg[tofind(i)].size();
        mx = max(mx, tt);
        for (int j = 0; j < gg[tofind(i)].size(); ++j) {
            for (int k = j + 1; k < gg[tofind(i)].size(); ++k) {
                int u = gg[tofind(i)][j];
                int v = gg[tofind(i)][k];
                if (!e[u][v]) {
                    ans++;
//                    cout << u << " " << v << endl;
                }
            }
        }
    }
    if (lenid != 0) {
//        cout << ans << endl;
//        cout << "ff" << endl;
        for (int i = 0; i < gg[togo].size(); ++i) {
            for (int j = i + 1; j < gg[togo].size(); ++j) {
                int u = gg[togo][i];
                int v = gg[togo][j];
                if (!e[u][v]) ans++;
            }
        }
    }
//    cout << ans << endl;
//    cout << gg[id[1]].size() << endl;
    ans += mx * gg[togo].size();
    cout << ans << endl;
}
int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    work();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6193873.html