http://uoj.ac/problem/171

带花树开花时的u和v一定要记清楚顺序,想好了再写,数据范围也要算好!

对每个筐子拆成3个点,连成一个三元环,对每个(u,v),让u和v的3个点都连边,这样跑一般图最大匹配(先增广每个球),可以发现所有的球都能放到一个筐子里,而且半空的筐子代表的三元环一定有一条边有匹配。

匹配总数=n+半空的筐子数,最大化匹配总数也相当于最大化半空的筐子数。

还可以发现三元环没必要连三条边,任选两个点连一条边也是一样的。

时间复杂度\(O(n^3)\)。

abclzr:“好神的建图啊,我一辈子也想不出来。”

reflash:“没关系,下辈子继续想。”

abclzr:“……”

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int N = 603;
const int M = 100003; struct node {int nxt, to;} E[M << 1];
int cnt, point[N], n, m, e, s[N], qu[N]; void ins(int u, int v) {E[++cnt] = (node) {point[u], v}; point[u] = cnt;} int tt[N], id[N], tot, fa[N], pre[N], Next[N]; int find(int x) {return fa[x] == x ? x : (fa[x] = find(fa[x]));} int p, q, tim = 0, vis[N];
int findlca(int u, int v) {
++tim;
while (true) {
if (u) {
if (vis[u] == tim)
return u;
vis[u] = tim;
u = find(pre[Next[u]]);
}
swap(u, v);
}
} void blossom(int u, int v, int lca) {
while (find(u) != lca) {
pre[u] = v;
v = Next[u];
if (s[v] == 1) {s[v] = 0; if (++q == N) q = 0; qu[q] = v;}
if (fa[u] == u) fa[u] = lca;
if (fa[v] == v) fa[v] = lca;
u = pre[v];
}
} int match(int x) {
memset(s, -1, sizeof(int) * (tot + 1));
for (int i = 1; i <= tot; ++i) fa[i] = i;
p = 0; q = 1; s[qu[1] = x] = 0; pre[x] = 0; int u, v;
while (p != q) {
if (++p == N) p = 0; u = qu[p];
for (int i = point[u]; i; i = E[i].nxt) {
v = E[i].to;
if (s[v] == -1) {
s[v] = 1; pre[v] = u;
if (!Next[v]) {
int last;
while (u) {
last = Next[u];
Next[u] = v; Next[v] = u;
u = pre[v = last];
}
return 1;
}
s[Next[v]] = 0; if (++q == N) q = 0; qu[q] = Next[v];
} else if (s[v] == 0 && find(u) != find(v)) {
int lca = findlca(fa[u], fa[v]);
blossom(u, v, lca);
blossom(v, u, lca);
}
}
} return 0;
} int main() {
int T; scanf("%d", &T);
while (T--) {
scanf("%d%d%d", &n, &m, &e);
tt[0] = n - 2;
for (int i = 1; i <= m; ++i) {
tt[i] = tt[i - 1] + 3;
id[tt[i]] = id[tt[i] + 1] = id[tt[i] + 2] = i;
} int u, v; tot = tt[m] + 2;
cnt = 0;
memset(point, 0, sizeof(int) * (tot + 1));
memset(Next, 0, sizeof(int) * (tot + 1)); for (int i = 1; i <= e; ++i) {
scanf("%d%d", &u, &v);
ins(u, tt[v]); ins(tt[v], u);
ins(u, tt[v] + 1); ins(tt[v] + 1, u);
ins(u, tt[v] + 2); ins(tt[v] + 2, u);
}
for (int i = 1; i <= m; ++i) ins(tt[i], tt[i] + 1), ins(tt[i] + 1, tt[i]); int ans = 0;
for (int i = 1; i <= tot; ++i)
if (!Next[i])
ans += match(i); printf("%d\n", ans - n);
for (int i = 1; i <= n; ++i)
printf("%d ", id[Next[i]]);
puts("");
} return 0;
}

最新文章

  1. Windows10下的JDK环境配置。
  2. ToolStripMenuItem
  3. JAVA_Android APK反编译就这么简单 详解(附图)
  4. How to install starDIct on suse OS?
  5. [z]查表空间使用情况
  6. 作业七:团队项目——Alpha版本冲刺阶段-13
  7. 百度的echart环形图颜色动态设置
  8. 如何优化TableView
  9. Yii2-Redis使用小记 - Cache
  10. api 翻译之AsyncTask
  11. 简单易懂的现代魔法&mdash;&mdash;Play Framework攻略2
  12. 《A First Course in Probability》-chaper7-期望的性质-期望的性质-协方差
  13. C++中struct和class的区别 [转]
  14. C# GC 垃圾回收
  15. sql server 2005中没有等于等于,高手自行跳过。。
  16. PD生成oracle表名带引号解决方案
  17. C语言总结
  18. android studio生成junitLibs
  19. 《转载》最新鲜最详细的Android SDK下载安装及配置教程
  20. 基于 HTML5 WebGL 的 3D 棉花加工监控系统

热门文章

  1. 【HDU】6012 Lotus and Horticulture (BC#91 T2)
  2. 【洛谷 P1707】 刷题比赛 (矩阵加速)
  3. idea 导入 java json 包
  4. perl模拟登录(1)
  5. 自己动手实现arm函数栈帧回溯【转】
  6. UNIX shell 学习笔记 一 : 几个shell的规则语法对比
  7. javascript 实现图片放大镜功能
  8. experss 做小型服务器出现跨域问题
  9. [].forEach.call($$(&quot;*&quot;),function(a){ a.style.outline=&quot;1px solid #&quot;+(~~(Math.random()*(1&lt;&lt;24))).toString(16) })
  10. 一、安装ansible