Codeforces Round #385 (Div. 2) C. Hongcow Builds A Nation 并查集
C. Hongcow Builds A Nation
链接:
http://codeforces.com/contest/745/problem/C
题解:
先把联通块全都搞出来;
显然那些不是特殊的联通块全都加在一起然后和特殊联通块中点数最多的合在一起能够形成的边更多.
则加在一起就好;
设这个联通块里面的点的个数为n;
则边的个数为n*(n-1)/2;
最后用总的边数减去m就好; 那些没有加非特殊联通块的特殊联通块也可以加边的,不要漏了。
代码:
1 #include <map> 2 #include <set> 3 #include <cmath> 4 #include <queue> 5 #include <stack> 6 #include <cstdio> 7 #include <string> 8 #include <vector> 9 #include <cstring> 10 #include <sstream> 11 #include <iostream> 12 #include <algorithm> 13 #include <functional> 14 using namespace std; 15 #define rep(i,a,n) for (int i=a;i<=n;i++) 16 #define per(i,a,n) for (int i=n;i>=a;i--) 17 #define pb push_back 18 #define mp make_pair 19 #define all(x) (x).begin(),(x).end() 20 #define SZ(x) ((int)(x).size()) 21 typedef vector<int> VI; 22 typedef long long ll; 23 typedef pair<int, int> PII; 24 const ll mod = 1e9 + 7; 25 const int inf = 0x3f3f3f3f; 26 const double eps = 1e-7; 27 // head 28 29 const int maxn = 1010; 30 int c[maxn]; 31 int par[maxn], num[maxn], sum[maxn]; 32 33 int find(int v) { 34 return par[v] = par[v] == v ? v : find(par[v]); 35 } 36 37 void merge(int x, int y) { 38 int a = find(x), b = find(y); 39 if (a != b) par[a] = b; 40 } 41 42 int main(){ 43 int n, m, k; 44 cin >> n >> m >> k; 45 rep(i, 1, k) cin >> c[i]; 46 rep(i, 1, n) par[i] = i; 47 rep(i, 1, m) { 48 int u, v; 49 cin >> u >> v; 50 merge(u, v); 51 } 52 rep(i, 1, n) sum[find(i)]++; 53 rep(i, 1, k) num[i] = sum[find(c[i])]; 54 int rest = n; 55 rep(i, 1, k) rest -= num[i]; 56 int po = max_element(num + 1, num + 1 + k) - num; 57 num[po] += rest; 58 int ans = 0; 59 rep(i, 1, k) ans += num[i] * (num[i] - 1) / 2; 60 cout << ans - m << endl; 61 return 0; 62 }