博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[WC2016]挑战NPC
阅读量:7248 次
发布时间:2019-06-29

本文共 2946 字,大约阅读时间需要 9 分钟。

Sol

这做法我是想不到\(TAT\)

每个筐子拆成三个相互连边

球向三个筐子连边
然后跑一般图最大匹配

这三个筐子间最多有一个匹配

那么显然每个球一定会放在一个筐子里,一定有一个匹配
如果筐子间有匹配,则有一个半空的筐子,因为它一定只匹配了小于等于\(1\)个球
答案为匹配数\(-n\)
使答案最大即匹配数最大

上带花树就好了

# include 
# define RG register# define IL inline# define Fill(a, b) memset(a, b, sizeof(a))using namespace std;typedef long long ll;const int _(1005);const int __(2e5 + 5);typedef int Arr[_];IL int Input(){ RG int x = 0, z = 1; RG char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1; for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48); return x * z;}Arr first, match, fa, vis, tim, pre;int n, m, cnt, idx, ans, E, t1, t2, t3;queue
Q;struct Edge{ int to, next;} edge[__];IL void Add(RG int u, RG int v){ edge[cnt] = (Edge){v, first[u]}, first[u] = cnt++; edge[cnt] = (Edge){u, first[v]}, first[v] = cnt++;}IL int Find(RG int x){ return x == fa[x] ? x : fa[x] = Find(fa[x]);}IL int LCA(RG int x, RG int y){ ++idx, x = Find(x), y = Find(y); while(tim[x] != idx){ tim[x] = idx; x = Find(pre[match[x]]); if(y) swap(x, y); } return x;}IL void Blossom(RG int x, RG int y, RG int p){ while(Find(x) != p){ pre[x] = y, y = match[x]; if(vis[y] == 2) vis[y] = 1, Q.push(y); if(Find(x) == x) fa[x] = p; if(Find(y) == y) fa[y] = p; x = pre[y]; }}IL int Aug(RG int S){ for(RG int i = 1; i <= t3; ++i) vis[i] = pre[i] = 0, fa[i] = i; while(!Q.empty()) Q.pop(); Q.push(S), vis[S] = 1; while(!Q.empty()){ RG int u = Q.front(); Q.pop(); for(RG int e = first[u]; e != -1; e = edge[e].next){ RG int v = edge[e].to; if(Find(v) == Find(u) || vis[v] == 2) continue; if(!vis[v]){ vis[v] = 2, pre[v] = u; if(!match[v]){ for(RG int x = v, lst; x; x = lst) lst = match[pre[x]], match[pre[x]] = x, match[x] = pre[x]; return 1; } vis[match[v]] = 1, Q.push(match[v]); } else{ RG int p = LCA(u, v); Blossom(u, v, p); Blossom(v, u, p); } } } return 0;}int main(RG int argc, RG char *argv[]){ for(RG int T = Input(); T; --T){ n = Input(), m = Input(), E = Input(); t1 = n + m, t2 = t1 + m, t3 = t2 + m; ans = cnt = idx = 0; for(RG int i = 1; i <= t3; ++i) first[i] = -1, match[i] = 0, tim[i] = 0; for(RG int i = 1; i <= m; ++i) Add(n + i, t1 + i), Add(t1 + i, t2 + i), Add(n + i, t2 + i); for(RG int i = 1, u, v; i <= E; ++i){ u = Input(), v = Input(); Add(u, n + v), Add(u, t1 + v), Add(u, t2 + v); } for(RG int i = 1; i <= t3; ++i) if(!match[i]) ans += Aug(i); printf("%d\n", ans - n); } return 0;}

转载于:https://www.cnblogs.com/cjoieryl/p/8658627.html

你可能感兴趣的文章
JavaScript学习笔记整理:对象篇
查看>>
GitHub的bug赏金计划升级:奖金提高到3万美元以上
查看>>
中国法院裁定:禁售部分型号苹果手机
查看>>
使用实体框架、Dapper和Chain的仓储模式实现策略
查看>>
HTTP/2推送之难,远超想象
查看>>
与Bob McWhirter的问答:WildFly Swarm更名为Thorntail项目
查看>>
新书问答:Agile Management
查看>>
在sublime中实现代码检测
查看>>
活在伟大的Scrum团队是什么感觉
查看>>
Swift 5进入发布倒计时
查看>>
一套代码称霸5大端口,移动金融应用还能这样开发?
查看>>
MIT开发Polaris,使网页载入加快34%
查看>>
微软对macOS和Linux开放量子开发工具集
查看>>
一份关于Angular的倡议清单
查看>>
没有估算,你仍然可以用这些决策策略
查看>>
通过调研开源基准测试集,解读大数据的应用现状和开源未来
查看>>
译文-调整G1收集器窍门
查看>>
时序数据库InfluxDB 2.0 alpha 发布:主推新的Flux查询语言,TICK栈将成为整体
查看>>
开源是项“全民工程”,揭秘开源团队的管理运作
查看>>
基于Gitflow分支模型自动化Java项目工作流
查看>>