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. 基于windows fiber的协程(coroutine)实现

    一个非常简单,但是实用的协程实现,使用Windows的*Fiber函数族(linux可以稍微改一下用*context函数族). fco.h #ifndef _MSC_VER #error " ...

  2. css 移动端图片等比显示处理

    第一次写博文,心情有点小小的激动~~~~~ 刚开始做移动端项目的时候遇到了一些优化的问题,比如,打开网页在2g或者3g的情况下加载网页,刚开始渲染的时候,遇到图片文件未请求,图片的高度会为0,当然,如 ...

  3. SQL SERVER中的二种获得自增长ID的方法

    新方法 insert into TblClass output inserted.tClassId values('Hi~班','英语班') 老方法 insert into 表名 () values ...

  4. 动手玩转Docker(一)

    在学习docker之前,先了解一下什么是docker,以及docker技术存在的意义. Docker是PaaS供应商dotCloud开源的一个基于LXC 的高级容器引擎,源代码托管在 GitHub 上 ...

  5. jenkins配置以cygwin环境的子节点

    1.为Cygwin配置上sshd服务 ⑴.双击点击如下安装文件,并一直选取下一步 ⑵.到这个步骤停止,并且在search栏里输入openssh,并下载搜出的两个程序 ⑶.下载好以后以管理员权限打开cy ...

  6. sql 简单语法

    1.数据库操作 create database student_info -- 创建数据库 drop database student_info -- 删除数据库 2.表操作 -- 创建表 creat ...

  7. python设计模式--读书笔记

    GoF在其设计模式一书中提出了23种设计模式,并将其分为三类: 创建型模式 将对象创建的细节隔离开来,代码与所创建的对象的类型无关. 结构型模式 简化结构,识别类与对象间的关系,重点关注类的继承和组合 ...

  8. 3dsmax2014卸载/安装失败/如何彻底卸载清除干净3dsmax2014注册表和文件的方法

    3dsmax2014提示安装未完成,某些产品无法安装该怎样解决呢?一些朋友在win7或者win10系统下安装3dsmax2014失败提示3dsmax2014安装未完成,某些产品无法安装,也有时候想重新 ...

  9. 【c++】explicit 隐式类类型转换

    上代码 #include <iostream> #include <sstream> using namespace std; class A { public: A(cons ...

  10. ASP.NET能知道的东西

    ASP.NET能知道的东西 获取服务器电脑名: Page.Server.ManchineName 获取用户信息: Page.User 获取客户端电脑名:Page.Request.UserHostNam ...