Sol

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

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

球向三个筐子连边

然后跑一般图最大匹配

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

那么显然每个球一定会放在一个筐子里,一定有一个匹配

如果筐子间有匹配,则有一个半空的筐子,因为它一定只匹配了小于等于\(1\)个球

答案为匹配数\(-n\)

使答案最大即匹配数最大

上带花树就好了

# include <bits/stdc++.h>
# 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 <int> 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;
}

[WC2016]挑战NPC的更多相关文章

  1. [WC2016]挑战NPC(一般图最大匹配)

    [WC2016]挑战NPC(一般图最大匹配) Luogu 题解时间 思路十分有趣. 考虑一个筐只有不多于一个球才有1的贡献代表什么. 很明显等效于有至少两个位置没有被匹配时有1的贡献. 进而可以构造如 ...

  2. [BZOJ]4405: [wc2016]挑战NPC(带花树)

    带花树模板 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; ...

  3. [bzoj4405][wc2016]挑战NPC

    来自FallDream的博客,未经允许,请勿转载,谢谢. 小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样的题目: 有n个球,用整数1到n编号.还有m个筐子,用整数1到m编号. ...

  4. BZOJ 4405 [wc2016]挑战NPC 带花树 一般图最大匹配

    https://www.lydsy.com/JudgeOnline/problem.php?id=4405 这道题大概就是考场上想不出来,想出来也调不出来的题. 把每个桶拆成三个互相有边的点,每个球向 ...

  5. [UOJ171][WC2016]挑战NPC

    uoj luogu bzoj sol 你可以列一个表格. 一个框子里放球的数量 0 1 2 3 对"半空框子"数量的贡献 1 1 0 0 把一个框子拆三个点.两两之间连边. 会发现 ...

  6. bzoj 4405: [wc2016]挑战NPC【带花树】

    把每个筐子拆成3个,分别表示放0/1/2个,然后把这三个点两两连起来,每一个可以放在筐里的球都想这三个点连边. 这样可以发现,放0个球的时候,匹配数为1,放1个球的时候,匹配数为1,放2个球的时候,匹 ...

  7. 「WC2016」挑战NPC

    「WC2016」挑战NPC 解题思路 这个题建图非常厉害,带花树什么的只会口胡根本写不动,所以我写了机房某大佬教我的乱搞. 考虑把一个筐 \(x\) 拆成 \(x1,x2,x3\) 三个点,且这三个点 ...

  8. 【BZOJ4405】【WC2016】挑战NPC(带花树)

    [BZOJ4405][WC2016]挑战NPC(带花树) 题面 BZOJ 洛谷 Uoj Description 小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样的题目: 有n个 ...

  9. UOJ171 【WC2016】挑战NPC

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

随机推荐

  1. leetcode-796-Rotate String

    题目描述: We are given two strings, A and B. A shift on A consists of taking string A and moving the lef ...

  2. 主流服务器虚拟化技术简单使用——Hyper-V(一)

    Tips:因为博客园排版的原因,图片显示不清晰,可以放大网页查看清晰图片. 如果系统使用物理机,需要在BIOS里面开启Intel VT-x(或AMD-V),如果是VMware workstation, ...

  3. js高级程序设计 笔记 --- DOM

    DOM是针对HTML和XML文档的一个API.DOM描绘了一个层次化的节点树,允许开发人员添加.移除和修改页面的某一部分. 1,节点层次 DOM可以将任何HTML或XML文档描绘成一个由多层节点构成的 ...

  4. js高级程序设计 笔记 --- 面向对象的程序设计

    1,理解对象 通过对象字面量的方式,创建一个对象,为它添加属性和方法: var obj = { a: 1, b:2, sayA(){ console.log(this.a)}} 1,属性类型: 数据属 ...

  5. 固定定位 z-index iconfont的使用 043

    固定定位  现象 脱标 提升层级  将盒子固定住 参考点 浏览器的左上角 : <!DOCTYPE html> <html lang="en"> <he ...

  6. 码云+jenkins+自动回复邮件

    码云和jenkins的配置流程在Gitee Jenkins Plugin上介绍的很仔细. 附上码云官方Gitee Jenkins Plugin的介绍: https://gitee.com/help/a ...

  7. linux 安装python

    wget https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tgz #下载安装包 tar zxvf Python-3.6.0.tgz #解压 . ...

  8. Redis中算法之——Raft算法

    Sentinel系统选举领头的方法是对Raft算法的领头选举方法的实现. 在分布式系统中一致性是很重要的.1990年Leslie Lamport提出基于消息传递的一致性算法Paxos算法,解决分布式系 ...

  9. @Transcational特性

    捕获RuntimeException 捕获Error 并不捕获Checked Exception 在方法中使用@Transcational注解时候,通过throw new Exception(),在发 ...

  10. (转)linux基本变量学习:位置变量$0 、$1 shift轮替、本地变量、环境变量、特殊变量

    原文:http://blog.51cto.com/woyaoxuelinux/1863045 shell: 弱类型编程语言 强:变量在使用前,必须事先声明,甚至还需要初始化: 弱:变量用时声明,甚至不 ...