Codeforces 745C:Hongcow Builds A Nation(并查集)
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(并查集)的更多相关文章
- C. Hongcow Builds A Nation 并查集
http://codeforces.com/contest/745/problem/C 把他们并查集后, 其他没有连去government的点,全部放去同一个并查集,然后选择一个节点数最多的gover ...
- Codeforces 744A. Hongcow Builds A Nation
A. Hongcow Builds A Nation 题意: 现在有 n 个点 ,m 条边组成了一个无向图 , 其中有 k 个特殊点, 这些特殊点之间不能连通 ,问可以再多加几条边? 因为$x^2+y ...
- 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 ...
- C. Hongcow Builds A Nation
C. Hongcow Builds A Nation time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- Codeforces Round #376 (Div. 2) C. Socks---并查集+贪心
题目链接:http://codeforces.com/problemset/problem/731/C 题意:有n只袜子,每只都有一个颜色,现在他的妈妈要去出差m天,然后让他每天穿第 L 和第 R 只 ...
- Codeforces 766D. Mahmoud and a Dictionary 并查集 二元敌对关系 点拆分
D. Mahmoud and a Dictionary time limit per test:4 seconds memory limit per test:256 megabytes input: ...
- Codeforces Round #541 (Div. 2) D 并查集 + 拓扑排序
https://codeforces.com/contest/1131/problem/D 题意 给你一个n*m二维偏序表,代表x[i]和y[j]的大小关系,根据表构造大小分别为n,m的x[],y[] ...
- CodeForces Roads not only in Berland(并查集)
H - Roads not only in Berland Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d ...
- codeforces div2 603 D. Secret Passwords(并查集)
题目链接:https://codeforces.com/contest/1263/problem/D 题意:有n个小写字符串代表n个密码,加入存在两个密码有共同的字母,那么说这两个密码可以认为是同一个 ...
随机推荐
- Java List操作
一.List:.有顺序以线性方式存储,可以存放重复对象 线程安全方法:List list = Collections.synchronizedList(new LinkedList(...)); ...
- jQuery的delegate()与proxy()方法
1. jQuery 事件 - delegate() 方法 定义和用法 delegate() 方法为指定的元素(属于被选元素的子元素)添加一个或多个事件处理程序,并规定当这些事件发生时运行的函数. 使用 ...
- 11G中自动收集统计信息
在11G中,引入了一个名为 gather_stats_prog 的自动运行任务专用于自动收集统计信息.其对应的客户端名称为"auto optimizer stats collection&q ...
- define 实例
// ----------------------------------------------define------------------------------------- // #def ...
- 给ubuntu系统换新装
此次安装主要按照Flatabulous:Ubuntu系统美化主题 但自己在安装过程中发现了很多问题,一下一段黑色的是上面链接的文章,红色的是自己在操作过程中的一些改动 安装主题的第一步是安装Ubunt ...
- IntelliJ IDEA 下的版本控制介绍
不管是个人开发或是团队开发,版本控制都是可以很好地被使用的,目前我找不到任何开发者不使用版本控制的理由.而且对于 IDE 来讲,集成版本控制的本身就是它最大的亮点之一,很多开发者也是为此而使用它. 在 ...
- HTML语言的一些元素(二)
3)表示元素:<b>,<i>,<u>,<s>,<tt>,<sup>,<sub>,<strike>,< ...
- Effective C++ 4.设计与声明
//条款18:让接口容易被正确使用,不易被误用 // 1.如果客户企图使用某个接口而却没有获得他所预期的行为,那么这个代码就不该通过编译. // 2.促进正确使用的方法包括接口的一致性,以及与内置类型 ...
- 初始化 Gradle 工程目录(转自: 隔叶黄莺 Unmi Blog)
最近重新在 Eclipse 中打开旧的 Maven 项目,总有些什么错误,备受折磨.期间试手了 Ant+Ivy, 现今试用了下 Gradle,感觉不错,它应该才是我真想要的,Maven 差不多该扔到一 ...
- 浅谈thinkphp中将字符串转换成json数组的方法
这是一部分代码: $client = M("Client");$data = $client->where('user_id ='.$user_id)->select( ...