Atcoder CODE FESTIVAL 2017 qual B C - 3 Steps 二分图
题目链接
题意
给定一个无向图,\(n\)个点,\(m\)条边(\(n,m\leq 1e5\)).
重复如下操作:
选择相异的两点u,v满足从点u出发走三条边恰好能到达点v。在这样的u,v点对之间添一条边(如果已经存在则无需再次添加)。
问最多能添加多少条边。
我的思路
(是写给自己看的读者老爷可以跳过去的部分)
首先, 所有距离为奇数的点对之间都能添边。因为
3-1+3=5
5-1+3=7
5-1+5=9
7-1+3=9
7-1+5=11
7-1+7=13
9-1+3=11
9-1+5=13
...
其次,如果距离为\(2\)的两点之间还有一条边,那么好像能够添成一个完全图……
然后就不会写了(卒
结论
如果该图为二分图,则最多能在所有黑点和白点之间加边;
如果不为二分图,则能加成一个完全图。
证明
官方题解
假设在\(s\)和\(t\)之间存在一条长度为奇数的路径,也就是说对于某个奇数\(k\),存在一个点的序列\(s=v_0,v_1,...,v_k=t\)(\(v_i\)和\(v_{i+1}\)相邻)。
如果\(k=1\),那么\(s\)和\(t\)之间本身就有一条边。如果\(k\geq 3\),通过在\(v_{k-3}\)和\(v_k\)之间加边,我们得到了一条\(s\)和\(t\)之间长度为\(k-2\)的路径。通过重复这个操作,我们可以一直减少\(s\)和\(t\)之间路径的长度最后在\(s\)和\(t\)之间加一条边。
这表示了奇数长路径的重要性,以及二分图性质的重要性。
Case 1. 不是二分图
不是二分图意味着存奇数长度的环,不妨设点\(v\)为环中的一点。因为图是连通图,所以对于任意的点对\((s,t)\),总有一条路径\(s\rightarrow v\rightarrow t\). 如果路径长度为偶数,则可通过加上点\(v\)处的奇环使得路径长度为奇数。
因此,在任意两点间都能找到一条奇数长度的路径,故可以将图加成一个完全图。所以答案为\(N(N-1)/2-M\).
Case 2. 是二分图
这种情况下,可以将点染成黑点和白点,每条边连接着一个白点和一个黑点。考虑任意的黑点和白点,因为图是连通图,所以黑点\(b\)和白点\(w\)之间存在着一条路径,并且显然路经长为奇数。因此,可以在\(b\)和\(w\)之间加边。另一方面,在同种颜色的点之间绝对无法加边。
故答案为\(BW-M\),\(B\)为白点个数,\(W\)为黑点个数。
具体写法
二分图的充要条件:所有回路长度均为偶数
法一:\(dfs\)
模拟染色看是否一个顶点会染到不同的颜色
法二(很新颖):并查集
具体解释见noip 2010 关押罪犯这道题的并查集做法
Code
Ver. 1 dfs
#include <bits/stdc++.h>
#define maxn 100010
using namespace std;
typedef long long LL;
struct Edge {
int to, ne;
Edge(int _to=0, int _ne=0): to(_to), ne(_ne) {}
}edge[maxn*2];
int tot, ne[maxn];
void add(int u, int v) {
edge[tot] = Edge(v, ne[u]);
ne[u] = tot++;
}
int n, m, c[maxn];
void dfs(int u, int col) {
c[u] = col;
for (int i = ne[u]; ~i; i = edge[i].ne) {
int v = edge[i].to;
if (c[v] == -1) dfs(v, !col);
if (c[v] != !col) { printf("%lld\n", 1LL*n*(n-1)/2-m); exit(0); }
}
}
int main() {
scanf("%d%d", &n, &m);
memset(c, -1, sizeof(c));
memset(ne, -1, sizeof(ne));
for (int i = 0; i < m; ++i) {
int u, v;
scanf("%d%d", &u, &v);
add(u, v);
add(v, u);
}
dfs(1, 0);
int b=0, w=0;
for (int i = 1; i <= n; ++i) if (c[i]) ++b; else ++w;
printf("%lld\n", 1LL*b*w-m);
return 0;
}
Ver. 2 并查集
#include <bits/stdc++.h>
#define maxn 200010
using namespace std;
typedef long long LL;
int fa[maxn], sz[maxn];
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
bool same(int u, int v) { return find(u) == find(v); }
void unionn(int x, int y) {
x = find(x), y = find(y);
if (sz[x] > sz[y]) swap(x, y);
fa[x] = y; sz[y] += sz[x];
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= (n<<1); ++i) fa[i] = i;
for (int i = 0; i < m; ++i) {
int u, v;
scanf("%d%d", &u, &v);
unionn(u, n+v);
unionn(n+u, v);
}
for (int i = 1; i <= n; ++i) if (same(i, n+i)) { printf("%lld\n", 1LL*n*(n-1)/2-m); return 0; }
int b = 1, w = 0;
for (int i = 2; i <= n; ++i) if (same(1, i)) ++b; else ++w;
printf("%lld\n", 1LL * b * w - m);
return 0;
}
Atcoder CODE FESTIVAL 2017 qual B C - 3 Steps 二分图的更多相关文章
- [AtCoder Code Festival 2017 QualB C/At3574] 3 Steps - 二分图染色,结论
给你一个n个点m条边的无向图,进行以下操作 如果存在两个点u和v,使得从u走三步能恰好到达v,那么在u和v之间连接一条边 重复这个操作直到不能再连接新的边,问最后有多少条边? n, m <= 1 ...
- CODE FESTIVAL 2017 qual B C - 3 Steps【二分图】
CODE FESTIVAL 2017 qual B C - 3 Steps 题意:给定一个n个结点m条边的无向图,若两点间走三步可以到,那么两点间可以直接连一条边,已经有边的不能连,问一共最多能连多少 ...
- Atcoder CODE FESTIVAL 2017 qual B D - 101 to 010 dp
题目链接 题意 对于一个\(01\)串,如果其中存在子串\(101\),则可以将它变成\(010\). 问最多能进行多少次这样的操作. 思路 官方题解 转化 倒过来考虑. 考虑,最终得到的串中的\(' ...
- 题解【AtCoder - CODE FESTIVAL 2017 qual B - D - 101 to 010】
题目:https://atcoder.jp/contests/code-festival-2017-qualb/tasks/code_festival_2017_qualb_d 题意:给一个 01 串 ...
- 【题解】Popping Balls AtCoder Code Festival 2017 qual B E 组合计数
蒟蒻__stdcall终于更新博客辣~ 一下午+一晚上=一道计数题QAQ 为什么计数题都这么玄学啊QAQ Prelude 题目链接:这里是传送门= ̄ω ̄= 下面我将分几个步骤讲一下这个题的做法,大家不 ...
- atcoder/CODE FESTIVAL 2017 qual B/B(dfs染色判断是否为二分图)
题目链接:http://code-festival-2017-qualb.contest.atcoder.jp/tasks/code_festival_2017_qualb_c 题意:给出一个含 n ...
- Atcoder CODE FESTIVAL 2017 qual C D - Yet Another Palindrome Partitioning 回文串划分
题目链接 题意 给定一个字符串(长度\(\leq 2e5\)),将其划分成尽量少的段,使得每段内重新排列后可以成为一个回文串. 题解 分析 每段内重新排列后是一个回文串\(\rightarrow\)该 ...
- Atcoder CODE FESTIVAL 2017 qual C C - Inserting 'x' 回文串
题目链接 题意 给定字符串\(s\),可以在其中任意位置插入字符\(x\). 问能否得到一个回文串,若能,需插入多少个\(x\). 思路 首先统计出现次数为奇数的字符\(cnt\). \(cnt\ge ...
- Atcoder CODE FESTIVAL 2017 qual B E - Popping Balls 组合计数
题目链接 题意 \(A+B\)个球排成一行,左边\(A\)个为红球,右边\(B\)个为蓝球. 最开始可以选择两个数\(s,t\),每次操作可以取左起第\(1\)或\(s\)或\(t\)个球.问有多少种 ...
随机推荐
- C# 使用Epplus导出Excel [5]:样式
C# 使用Epplus导出Excel [1]:导出固定列数据 C# 使用Epplus导出Excel [2]:导出动态列数据 C# 使用Epplus导出Excel [3]:合并列连续相同数据 C# 使用 ...
- json_decode()和json_encode()区别----2015-0929
json_decode对JSON格式的字符串进行编码而json_encode对变量进行 JSON 编码,需要的朋友可以参考下 1.json_decode() json_decode (PHP 5 ...
- Codevs3324 新斯诺克
题目描述 Description 斯诺克又称英式台球,是一种流行的台球运动.在球桌上,台面四角以及两长边中心位置各有一个球洞,使用的球分别为1 个白球,15 个红球和6 个彩球(黄.绿.棕.蓝.粉红. ...
- NOIP模拟赛 密室逃脱
密室逃脱(maze.*) 即使czhou没有派出最强篮球阵容,机房篮球队还是暴虐了校篮球队.为了不打击校篮球队信心,czhou决定改变训练后的活动.近来,江大掌门的徒弟徒孙们纷纷事业有成,回到母校为机 ...
- 初涉manacher
一直没有打过……那么今天来找几道题打一打吧 manacher有什么用 字符串的题有一类是专门关于“回文”的.通常来说,这类问题要么和一些dp结合在一起:要么是考察对于manacher(或其他如回文自动 ...
- angular5 HttpInterceptor使用
HttpInterceptor接口是ng的http请求拦截器,当需要拦截http请求,可以实现该接口. 1.创建HttpInterceptor 的实现类,并使用@Injectable()注解 @Inj ...
- Linux下的jdk安装
我使用的是CentOS7,jdk使用的是JDK1.8 下载好以后,将jdk传到我自己的目录:/home/tool下,通过 tar -xzvf jdk-8u131-linux-x64.tar.gz解压 ...
- 使用Github第一节
学习Github 1.目的: 借助github托管代码 2.基本概念(1): 仓库(Repository) 仓库用来存放项目代码,每个项目对应一个仓库,多个项目则对应多个仓库 收藏(Start) 收藏 ...
- UVA - 11572 Unique Snowflakes 滑动扫描
题目:点击打开题目链接 思路:从左往右扫描,定义扫描左端点L,右端点R,保证每次往几何中添加的都是符合要求的连续的数列中的元素,L和R从0扫到n,复杂度为O(n),使用set维护子数列,set查找删除 ...
- selenium2中的TestNg注解和数据驱动的简介及使用
TestNg常用注解介绍,先来张图: 先看一下,以上各个注释的运行次序: @Test 表示的意义: 1.表示示该方法是一个测试方法,在运行时,会自动的运行有@Test注脚的方法. 示例: @Be ...