[UOJ171][WC2016]挑战NPC
sol
你可以列一个表格。
| 一个框子里放球的数量 | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| 对“半空框子”数量的贡献 | 1 | 1 | 0 | 0 |
把一个框子拆三个点。两两之间连边。
会发现,如果这三个点里一个都没有被球匹配掉,那么这三个点的最大匹配数是\(1\);如果任意一个点被一个球匹配掉了,那么剩下两个点一定可以匹配,所以最大匹配数还是\(1\);有两个点或者是三个点被匹配后最大匹配就是\(0\)。
所以,按如上方式建图,每个球向它可以放进的框子对应的的三个点都连边。跑出最大匹配后输出\(ans-n\)就好了。(因为\(n\)个球是一定可以被匹配的)
update:yyb跟我说他在WA了若干次后发现了一件有趣的事情。
因为只有增广成功时才会修改匹配,所以如果先匹配框子再匹配球的话,不能保证球一定出现在最大匹配中,所以在输出方案的时候会出问题。
所以就一定要先匹配球再匹配框子。
code
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
int gi()
{
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 1005;
int T,n,m,q,to[N*N],nxt[N*N],head[N],cnt;
int match[N],vis[N],pre[N],fa[N],tim[N],idx,ans;
queue<int>Q;
void link(int u,int v)
{
to[++cnt]=v;nxt[cnt]=head[u];
head[u]=cnt;
to[++cnt]=u;nxt[cnt]=head[v];
head[v]=cnt;
}
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
int lca(int x,int y)
{
for (++idx;;swap(x,y))
if (x)
{
x=find(x);
if (tim[x]==idx) return x;
else tim[x]=idx,x=pre[match[x]];
}
}
void blossom(int x,int y,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];
}
}
int Aug(int S)
{
for (int i=n+3*m;i;--i)
vis[i]=pre[i]=0,fa[i]=i;
while (!Q.empty()) Q.pop();
Q.push(S);vis[S]=1;
while (!Q.empty())
{
int u=Q.front();Q.pop();
for (int e=head[u];e;e=nxt[e])
{
int v=to[e];
if (find(u)==find(v)||vis[v]==2) continue;
if (!vis[v])
{
vis[v]=2;pre[v]=u;
if (!match[v])
{
for (int x=v,lst;x;x=lst)
lst=match[pre[x]],match[x]=pre[x],match[pre[x]]=x;
return 1;
}
vis[match[v]]=1;Q.push(match[v]);
}
else
{
int gg=lca(u,v);
blossom(u,v,gg);blossom(v,u,gg);
}
}
}
return 0;
}
int main()
{
T=gi();
while (T--)
{
n=gi();m=gi();q=gi();cnt=idx=ans=0;
for (int i=n+3*m;i;--i) head[i]=match[i]=tim[i]=0;
for (int i=1;i<=q;++i)
{
int u=gi(),v=gi();
link(u+3*m,v),link(u+3*m,v+m),link(u+3*m,v+2*m);
}
for (int i=1;i<=m;++i)
link(i,i+m),link(i,i+2*m),link(i+m,i+2*m);
for (int i=n+3*m;i;--i) if (!match[i]) ans+=Aug(i);
printf("%d\n",ans-n);
for (int i=1+3*m;i<=n+3*m;++i) printf("%d ",(match[i]-1)%m+1);
puts("");
}
return 0;
}
[UOJ171][WC2016]挑战NPC的更多相关文章
- [WC2016]挑战NPC(一般图最大匹配)
[WC2016]挑战NPC(一般图最大匹配) Luogu 题解时间 思路十分有趣. 考虑一个筐只有不多于一个球才有1的贡献代表什么. 很明显等效于有至少两个位置没有被匹配时有1的贡献. 进而可以构造如 ...
- [BZOJ]4405: [wc2016]挑战NPC(带花树)
带花树模板 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; ...
- [bzoj4405][wc2016]挑战NPC
来自FallDream的博客,未经允许,请勿转载,谢谢. 小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样的题目: 有n个球,用整数1到n编号.还有m个筐子,用整数1到m编号. ...
- BZOJ 4405 [wc2016]挑战NPC 带花树 一般图最大匹配
https://www.lydsy.com/JudgeOnline/problem.php?id=4405 这道题大概就是考场上想不出来,想出来也调不出来的题. 把每个桶拆成三个互相有边的点,每个球向 ...
- [WC2016]挑战NPC
Sol 这做法我是想不到\(TAT\) 每个筐子拆成三个相互连边 球向三个筐子连边 然后跑一般图最大匹配 这三个筐子间最多有一个匹配 那么显然每个球一定会放在一个筐子里,一定有一个匹配 如果筐子间有匹 ...
- bzoj 4405: [wc2016]挑战NPC【带花树】
把每个筐子拆成3个,分别表示放0/1/2个,然后把这三个点两两连起来,每一个可以放在筐里的球都想这三个点连边. 这样可以发现,放0个球的时候,匹配数为1,放1个球的时候,匹配数为1,放2个球的时候,匹 ...
- 「WC2016」挑战NPC
「WC2016」挑战NPC 解题思路 这个题建图非常厉害,带花树什么的只会口胡根本写不动,所以我写了机房某大佬教我的乱搞. 考虑把一个筐 \(x\) 拆成 \(x1,x2,x3\) 三个点,且这三个点 ...
- 【BZOJ4405】【WC2016】挑战NPC(带花树)
[BZOJ4405][WC2016]挑战NPC(带花树) 题面 BZOJ 洛谷 Uoj Description 小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样的题目: 有n个 ...
- UOJ171 【WC2016】挑战NPC
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
随机推荐
- Loadrunder脚本篇——web_submit_data实现提交post请求
概述 web_link()和web_url()函数都是页面访问型函数,实现HTTP请求中的GET方法,如果需要实现POST方法,可使用web_submit_form或web_submit_data() ...
- iOS 52个技巧学习心得笔记 第一章 熟悉OC
1 .简单了解OC2 .在类的头文件中尽量少引入其他头文件3 .多用字面量语法 少用与之等价的方法 4 .多用类型常量 少用 #define 预处理指令5 .用枚举表示状态,选项,状态码 .简单了解O ...
- Swift进阶 - 12个技巧
听说你已经学习Swift几个月了,有没有想更进一步成为Swift高手的想法?我这里有11招秘技,各位施主且听我慢慢道来,结个善缘. 1. 扩展(Extension) 任务: 求数字的平方. // 菜鸟 ...
- Linux软件包管理 RMP包
RPM 包的安装虽然很方便和快捷,但是依赖性实在是很麻烦,尤其是库文件依赖,还要去 rpmfind 网站査找库文件到底属于哪个 RPM 包,从而导致 RPM 包的安装非常烦琐.那么,有没有可以自动解决 ...
- Linux基本命令 权限管理命令
1.权限管理命令chmod ================================================================================== 命令名 ...
- HTTP学习笔记01-URL
URI URL语法 相对URL和绝对URL 相对URL URL的常用协议 http https mailto ftp rtsprtspu file news telnet 展望美好的未来 1.URI ...
- samtools+bcftools 进行SNP calling
两个软件的作用:1.samtools mpileup 主要是用于收集BAM文件中的信息,这个位点上有多少条read匹配,匹配read的碱基是什么,并将这些信息存储在BCF文件中.2.bcftools ...
- Django详解之四、cookie和session
一.使用背景 思路 简单的后台管理:对人员的管理 1. 登录注册 2. 老师 班级管理 学院管理 3. 增删改查 开发: 1. 定义数据库表结构 a) 表结构关系 i. class classes(m ...
- windows7 安装Apache2时出现failed to open the winNT service manager 提示
因为电脑实在太慢了,C盘的空间所剩无几,要想再安装大一点的软件的话,可能性很小.加之系统已经好久没有重装过了,于是重新安装windows7旗舰版,系统装好后,免不了一堆软件的重装和开发环境配置,首要的 ...
- JSP--内置对象&动作标签介绍
1.JSP中常用的9大内置对象? 内置对象:在JSP页面中能直接使用的对象就是JSP内置对象,事实上,JSP底层就是一个java类,可以在JSP中直接使用的,必然存在JSP翻译后的java类 下面简单 ...