http://codeforces.com/problemset/problem/744/A

题意:在一个图里面有n个点m条边,还有k个点是受限制的,即不能从一个受限制的点走到另外一个受限制的点(有路径相连),问在这样的图里面遵守这样的规则可以最多添加几条边。

思路:这种题之前在做强连通的时候很常见,于是就写了tarjan。。醒来后发现不用这么复杂,直接用并查集就可以做了。

1、对于每一个连通块,最多可以加上n*(n-1)/2条边。

2、对于受限制的连通块,取出一个点数最多的,和不受限制的块相连。

3、对于不受限制的连通块,两两之间可以相连。

4、由于有重复,所以减去初始的m条边。

并查集:

 #include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
typedef long long LL;
int sum[], c[], fa[], tag[];
vector<int> vec; int Find(int x) {
if(x == fa[x]) return x;
return fa[x] = Find(fa[x]);
} void Merge(int x, int y) {
x = Find(x), y = Find(y);
if(x == y) return ;
fa[x] = y;
sum[y] += sum[x];
} int main() {
int n, m, k;
cin >> n >> m >> k;
for(int i = ; i <= k; i++) cin >> c[i];
for(int i = ; i <= n; i++) fa[i] = i, sum[i] = ;
for(int i = ; i <= m; i++) {
int u, v;
cin >> u >> v;
Merge(u, v);
}
int ans = -m, ma = ;
for(int i = ; i <= k; i++) tag[Find(c[i])] = ; // 标记受限制的块
for(int i = ; i <= n; i++) {
if(fa[i] == i) {
if(tag[i]) ma = max(sum[i], ma);
else vec.push_back(sum[i]);
ans += sum[i] * (sum[i] - ) / ; // 每个连通块里面最大边数
}
}
int sz = vec.size();
for(int i = ; i < sz; i++) {
for(int j = i + ; j < sz; j++) {
ans += vec[i] * vec[j]; // 不受限制的连通块之间连边
}
ans += vec[i] * ma; // 受限制的取最大的和不受限制的连边
}
cout << ans << endl;
return ;
}

tarjan:

 #include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <stack>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
typedef long long LL;
struct node {
int u, v, nxt;
}edge[*N];
struct P {
int id, num;
}p[];
int head[], tot, cnt, num;
int belong[], dfn[], low[], c[], vis[];
stack<int> sta;
vector<int> v1, v2; void add(int u, int v) {
edge[tot].v = v; edge[tot].nxt = head[u]; head[u] = tot++;
} void tarjan(int u) {
dfn[u] = low[u] = ++cnt;
vis[u] = ; sta.push(u);
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(!dfn[v]) {
tarjan(v);
if(low[v] < low[u]) low[u] = low[v];
} else if(vis[v]) {
if(dfn[v] < low[u]) low[u] = dfn[v];
}
}
if(dfn[u] == low[u]) {
++num;
while(true) {
int v = sta.top(); sta.pop();
belong[v] = num; vis[v] = ;
if(v == u) break;
}
}
} int main() {
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
for(int i = ; i < k; i++) scanf("%d", c + i);
memset(head, -, sizeof(head));
memset(vis, , sizeof(vis));
tot = num = cnt = ;
for(int i = ; i < m; i++) {
int u, v;
scanf("%d%d", &u, &v);
add(u, v); add(v, u);
}
for(int i = ; i <= n; i++)
if(!dfn[i]) tarjan(i);
v1.clear(); v2.clear();
for(int i = ; i <= num; i++) {
for(int j = ; j <= n; j++) {
if(belong[j] == i) {
p[i].num++;
}
}
}
for(int i = ; i < k; i++)
p[belong[c[i]]].id = ;
for(int i = ; i <= num; i++) {
if(p[i].id == ) v1.push_back(p[i].num);
else v2.push_back(p[i].num);
}
sort(v1.begin(), v1.end());
sort(v2.begin(), v2.end());
int sz = v1.size();
int szz = v2.size();
LL ans = ;
for(int i = ; i < szz; i++)
ans += v1[sz-] * v2[i];
for(int i = ; i < szz; i++) {
for(int j = i + ; j < szz; j++) {
ans += v2[i] * v2[j];
}
ans += v2[i] * (v2[i]-) / ;
} for(int i = ; i < sz; i++)
ans += (v1[i]-) * v1[i] / ;
ans -= m;
printf("%I64d\n", ans);
return ;
} /*
8 4 2
4 5
1 2
6 7
7 8
2 4
*/

Codeforces 745C:Hongcow Builds A Nation(并查集)的更多相关文章

  1. C. Hongcow Builds A Nation 并查集

    http://codeforces.com/contest/745/problem/C 把他们并查集后, 其他没有连去government的点,全部放去同一个并查集,然后选择一个节点数最多的gover ...

  2. Codeforces 744A. Hongcow Builds A Nation

    A. Hongcow Builds A Nation 题意: 现在有 n 个点 ,m 条边组成了一个无向图 , 其中有 k 个特殊点, 这些特殊点之间不能连通 ,问可以再多加几条边? 因为$x^2+y ...

  3. Codeforces Round #385 (Div. 2) Hongcow Builds A Nation —— 图论计数

    题目链接:http://codeforces.com/contest/745/problem/C C. Hongcow Builds A Nation time limit per test 2 se ...

  4. C. Hongcow Builds A Nation

    C. Hongcow Builds A Nation time limit per test 2 seconds memory limit per test 256 megabytes input s ...

  5. Codeforces Round #376 (Div. 2) C. Socks---并查集+贪心

    题目链接:http://codeforces.com/problemset/problem/731/C 题意:有n只袜子,每只都有一个颜色,现在他的妈妈要去出差m天,然后让他每天穿第 L 和第 R 只 ...

  6. Codeforces 766D. Mahmoud and a Dictionary 并查集 二元敌对关系 点拆分

    D. Mahmoud and a Dictionary time limit per test:4 seconds memory limit per test:256 megabytes input: ...

  7. Codeforces Round #541 (Div. 2) D 并查集 + 拓扑排序

    https://codeforces.com/contest/1131/problem/D 题意 给你一个n*m二维偏序表,代表x[i]和y[j]的大小关系,根据表构造大小分别为n,m的x[],y[] ...

  8. CodeForces Roads not only in Berland(并查集)

    H - Roads not only in Berland Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d ...

  9. codeforces div2 603 D. Secret Passwords(并查集)

    题目链接:https://codeforces.com/contest/1263/problem/D 题意:有n个小写字符串代表n个密码,加入存在两个密码有共同的字母,那么说这两个密码可以认为是同一个 ...

随机推荐

  1. python 模块zlib 压缩与解压

    例子1:压缩与解压字符串 import zlib message = 'abcd1234' compressed = zlib.compress(message) decompressed = zli ...

  2. Gunicorn + Django 部署

    1. 下载gunicorn pip install gunicorn 2. 运行 gunicorn AutoSa.wsgi:application ## AutoSa为我project的名字,后面的不 ...

  3. c#异步调用

    首先来看一个简单的例子: 小明在烧水,等水烧开以后,将开水灌入热水瓶,然后开始整理家务 小文在烧水,在烧水的过程中整理家务,等水烧开以后,放下手中的家务活,将开水灌入热水瓶,然后继续整理家务 这也是日 ...

  4. SqlServer StringToTable性能测试

    问题起因: 最近做的项目DB数据量比较大(基本上一个月的数据就是10亿),而工程中Proc参数中包含有id拼接字符串,id拼接字符串格式:1,2,4,5,100,301.当数据量很小的情况下,这样做没 ...

  5. 通用窗口类 Inventory Pro 2.1.2 Demo1(上)

    插件功能 按照Demo1的实现,使用插件来实现一个装备窗口是很easy的,虽然效果还很原始但是也点到为止了,本篇涉及的功能用加粗标出,具体的功能如下: 1.实现了两个窗口,通过点击键盘I来,打开或者关 ...

  6. JDK JVM

  7. Smarty模板

    Smarty模板 是做什么用的?? 是将前端的显示和后台的逻辑进行分离,就相当于把前台显示的页面和后台要实现的某些功能的逻辑给分离出来了,分离在两个文件里,也就是说,前端只负责显示,后端只负责逻辑操作 ...

  8. JS小练习 留言功能

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. [原创]java WEB学习笔记53:Struts2学习之路---前奏:使用 Filter 作为控制器的 MVC

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  10. 构造方法特点,void

    构造方法特点: 1.和类有相同的名字 2.无返回值 3.被默认强制void void作用:====>>说明声明的方法没有返回值 构造方法作用: -->初始化实例属性 -->用于 ...