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; }