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个密码,加入存在两个密码有共同的字母,那么说这两个密码可以认为是同一个 ...
随机推荐
- selenium 基本了解
Selenium的界面 白色:还未执行 浅青色:动作成功 深青色:判断成功 浅粉红色:判断失败,但不影响测试案例的运行 深粉红色:判断失败,且测试案例无法正常运行 Command 存在的命令 Acti ...
- python_计算一段文本各个字符的出现个数
>题目要求 任意给定一段文本,求出每个字符出现的个数,并且打印出来 >程序实现 import pprint str01 = "重庆市,简称巴和渝,别称山城.渝都.雾都.桥都,中华 ...
- MSBUID相关(笔记)
用于创建可靠的最佳实践 Build,Part 1 http://msdn.microsoft.com/zh-cn/magazine/dd419659.aspx 用于创建可靠的最佳实践 Build,Pa ...
- [Sublime Text] How to Install Sublime Text on Ubuntu
For Sublime-Text-2: sudo add-apt-repository ppa:webupd8team/sublime-text- sudo apt-get update sudo a ...
- php:mysqli扩展
mysqli功能概述:http://php.net/manual/zh/mysqli.summary.php 代码(基本的用法):貌似可以防止sql注入 $root = "root" ...
- PostgreSQL Type的创建与Type在函数中的使用
postgres=# create type complex as(postgres(# r double precision,postgres(# i double precisionpostgre ...
- HTML--表单,图片热点,网页划区和拼接
一.图片热点 规划出图片上的一个区域,可以做出超链接,直接点击图片区域就可以完成跳转的效果. 示例: <img src="/ usemap="longzhu"> ...
- sdutoj 2152 Balloons
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2152 Balloons Time Limit: ...
- csuoj 1335: 高桥和低桥
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1335 1335: 高桥和低桥 Time Limit: 1 Sec Memory Limit: 1 ...
- csuoj 1334: 好老师
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1334 1334: 好老师 Time Limit: 1 Sec Memory Limit: 128 ...