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个密码,加入存在两个密码有共同的字母,那么说这两个密码可以认为是同一个 ...
随机推荐
- mysql 快速生成百万条测试数据
1.生成思路 利用mysql内存表插入速度快的特点,先利用函数和存储过程在内存表中生成数据,然后再从内存表插入普通表中 2.创建内存表及普通表 CREATE TABLE `vote_record_me ...
- Map的基本用法(Java)
package home.collection.arr; import java.awt.Window.Type; import java.util.ArrayList; import java.ut ...
- Chrome模拟手机浏览网页
用Chrome模拟手机浏览网页,只需要编辑一个命令就可以实现 C:\Users\xxx\AppData\Local\Google\Chrome\Application\chrome.exe --use ...
- 磁盘io负载查看
转自:http://blog.csdn.net/i_am_jojo/article/details/7698458 为了方便各位和自己今后遇到此类问题能尽快解决,我这里将查看linux服务器硬盘IO访 ...
- screen命令学习
我们有时需要做一些长时间的工作,比如格式化一个20T的raid磁盘,可能需要几个小时以上,如果只是执行格式化的话,由于网络不稳定,或者要下班了,还没格式化完成,关闭了ssh的窗口,命令可能就执行失败了 ...
- C#处理JSON数据
每次写博客,第一句话都是这样的:程序员很苦逼,除了会写程序,还得会写博客!当然,希望将来的一天,某位老板看到此博客,给你的程序员职工加点薪资吧!因为程序员的世界除了苦逼就是沉默.我眼中的程序员大多都不 ...
- Lintcode: Kth Smallest Number in Sorted Matrix
Find the kth smallest number in at row and column sorted matrix. Example Given k = 4 and a matrix: [ ...
- [转]10个顶级的CSS UI开源框架
随着CSS3和HTML5的流行,我们的WEB页面不仅需要更人性化的设计理念,而且需要更酷的页面特效和用户体验.作为开发者,我们需要了解一些宝贵的CSS UI开源框架资源,它们可以帮助我们更快更好地实现 ...
- Java基础(35):装箱与拆箱---Java 中基本类型和包装类之间的转换(Wrapper类)
基本类型和包装类之间经常需要互相转换,以 Integer 为例(其他几个包装类的操作雷同哦): 在 JDK1.5 引入自动装箱和拆箱的机制后,包装类和基本类型之间的转换就更加轻松便利了. 那什么是装箱 ...
- yii中sphinx,Ajax搜索分页
效果图: 控制器: <?phpnamespace backend\controllers; use Yii;use yii\web\Controller;use yii\data\Paginat ...