大体题意:
给你n 个点m个边的图,告诉其中一些点是政府点,如果任意两个政府点 不能直接或者间接到达的话,那么称这个图就是一个稳定的图,要求让你在这个图中加尽量多的边,使得 这个图还是稳定的!
思路:
其实思路很简单:简单的并查集应用!
因为题目保证输入的图一定是一个稳定的图,那么每一个政府点 都在一个独立的并查集内部!
我们先给每一个并查集内部的点进行连接! 任意连接都是合法的!
然后把所有不包括政府点的 独立并查集 归结到 最大包含政府点的并查集的内部!
然后求每一个并查集的完全图即可!
详细见代码:
加上数学计算的代码:
#include <bits/stdc++.h>
#define Size(x) ((int)(x).size())
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 1000 + 10;
int fa[maxn], belong[maxn],a[maxn],have[maxn];
set<int>g[maxn];
int id = 0;
int find(int x){
return fa[x] == x ? fa[x] : fa[x] = find(fa[x]);
}
int main(){
int n,m , k;
scanf("%d %d %d",&n, &m, &k);
for (int i = 1; i <= n; ++i)fa[i] = i;
for (int i = 0; i < k; ++i) scanf("%d",a+i);
for (int i = 0; i < m; ++i){
int u,v;
scanf("%d %d",&u, &v);
fa[find(u)] = find(v);
}
for (int i = 1; i <= n; ++i){
if (find(i) == i){
for (int j = 1; j <= n; ++j){
if (find(j) == i) g[id].insert(j), belong[j] = id;
}
++id;
}
}
int sum = 0;
int Max = -1,po;
for (int i = 0; i < k; ++i){
int v = a[i];
int pos = belong[v];
have[pos]++;
int t = Size(g[pos]);
if (t > Max){
Max = t;
po = pos;
}
}
int sum2 = 0;
for (int i = 0; i < id; ++i){
if (!have[i])sum2 += Size(g[i]);
}
// printf("sum2 = %d\n",sum2);
for (int i = 0; i < id; ++i){
if (have[i]){
int t;
if (i != po){
t = Size(g[i]);
}
else t = Size(g[po]) + sum2;;
// printf(" t = %d\n",t);
sum += t * (t-1)/2;
}
}
printf("%d\n",sum - m);
return 0;
}
纯暴力的代码:
#include <bits/stdc++.h>
#define Size(x) ((int)(x).size())
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 1000 + 10;
int fa[maxn], belong[maxn],a[maxn],have[maxn];
set<int>g[maxn];
int id = 0;
int find(int x){
return fa[x] == x ? fa[x] : fa[x] = find(fa[x]);
}
int main(){
int n,m , k;
scanf("%d %d %d",&n, &m, &k);
for (int i = 1; i <= n; ++i)fa[i] = i;
for (int i = 0; i < k; ++i) scanf("%d",a+i);
for (int i = 0; i < m; ++i){
int u,v;
scanf("%d %d",&u, &v);
fa[find(u)] = find(v);
}
for (int i = 1; i <= n; ++i){
if (find(i) == i){
for (int j = 1; j <= n; ++j){
if (find(j) == i) g[id].insert(j), belong[j] = id;
}
++id;
}
}
int sum = 0;
int Max = -1,po;
for (int i = 0; i < k; ++i){
int v = a[i];
int pos = belong[v];
have[pos]++;
int t = Size(g[pos]);
if (t > Max){
Max = t;
po = pos;
}
}
int sum2 = 0;
for (int i = 0; i < id; ++i){
if (!have[i])sum2 += Size(g[i]);
}
// printf("sum2 = %d\n",sum2);
for (int i = 0; i < id; ++i){
if (have[i]){
int t;
if (i != po){
t = Size(g[i]);
}
else t = Size(g[po]) + sum2;;
// printf(" t = %d\n",t);
sum += t * (t-1)/2;
}
}
printf("%d\n",sum - m);
return 0;
}