图论 - 生成树
UVA10600 ACM Contest and Blackout
求最小生成树后,枚举每一条没有用到的边u, v, w,求u到v路径上的最大边权,最后得到次小生成树
图论 - 双连通
LOJ1026 Critical Links 桥板题
LOJ1063 Ant Hills 割点板题
LOJ1291 Real Life Traffic
添加最少的边,使整张图边双连通
将原图分解为边双连通分量建树, 添加的边的数量为 (叶子数量 + 1) / 2
LOJ1300 Odd Personality
统计满足条件的点的数量,要求能从该点出发,不重复地经过奇数条边回到该点
将原图分解为边双连通分量,从一个分量内出发不能经过另一个分量,不然就回不来,因为分量由桥分割。然后检查每个分量是否是二分图,不是二分图表示该分量内有奇环,将分量内所有点加入答案
CF118E / CSES2177
给定无向图,给每条边一个方向,是否能使得新得到的有向图强连通,
如果无向图存在桥 (u, v) 将图分成两半,且方向为 u -> v, 那么 从v 的一端就不能到达 u 的一端
图论 - 网络流
CF498C
给定数组和一些二元组,每个二元组为一个奇数+一个偶数,每次可以选择一个二元组,将对应元素除以它们的一个公因数,求最大操作次数
对每个数做质因数分解,对每个质数建二分图,从源点到奇数点连边,边权为质数数量,从偶数点到汇点连边,边权为质数数量,对每个二元组连边,边权为二者质数数量的最小值,跑最大流
图论 - 二分图匹配
LOJ1149 Factors and Multiples
LOJ1201 A Perfect Murder
LOJ1184 Marriage Media
LOJ1206 Scheduling Taxi Cabs
LOJ1203 Air Raid
CSA No Prime Sum 最小点覆盖 / 输出合法方案
删去最少的元素,使剩下的元素两两相加均不为质数
先求最大匹配,将匹配上的边记为从左向右,未匹配上的边记为从右向左,对左侧每个未被匹配到的点跑dfs,最后左侧所有未被访问的点和右侧所有被访问的点就是最小点覆盖
void dfs2(int x) {
if (vis[x]) return;
vis[x] = 1;
for (auto to : a[x]) {
if (match[to] != -1 && match[to] != x) {
vis[to] = 1;
dfs2(match[to]);
}
}
}
CSA Flipping Matrix
Gym101666E Easter Eggs
给定红色和蓝色的点,选至少n个点,使得红色点和蓝色点的最大值最小
只关心红色点和蓝色点的距离,把红色点和蓝色点放到两侧连边,就是二分图。二分查找答案,每次只用符合条件的边进行匹配
LOJ1356 Prime Independence 最大独立集 / Hopcroft-Karp
求最大集合,使得不存在一个数被另一个数整除结果为质数的情况
数据较大,用 Hopcropft-Karp求最大匹配
namespace HK {
int match[maxn];
int dist[maxn];
int n;
void init(int _n) {
n = _n;
memset(match, 0, sizeof match);
}
bool dfs(int x) {
if (x) {
for (auto to : a[x]) {
int& u = match[to];
if (dist[u] == dist[x] + 1 && dfs(u)) {
match[to] = x;
match[x] = to;
return true;
}
}
dist[x] = INF;
return false;
}
return true;
}
bool bfs() {
queue<int> q;
for (int i = 1; i <= n; ++i) {
if (!match[i]) {
dist[i] = 0;
q.emplace(i);
} else {
dist[i] = INF;
}
}
dist[0] = INF;
while (!q.empty()) {
int x = q.front(); q.pop();
if (x) {
for (auto to : a[x]) {
if (dist[match[to]] == INF) {
dist[match[to]] = dist[x] + 1;
q.emplace(match[to]);
}
}
}
}
return dist[0] != INF;
}
int go() {
int res = 0;
while (bfs()) {
for (int i = 1; i <= n; ++i) {
if (match[i] == 0 && dfs(i)) {
res++;
}
}
}
return res;
}
}
Codechef Sereja and Graph
给定无向图,能否删除一些边,使得每个点的度数为1
相当于做一般图匹配,用Edmond Blossom检查是否存在完美匹配