[WC2016]挑战NPC(一般图最大匹配)
[WC2016]挑战NPC(一般图最大匹配)
题解时间
思路十分有趣。
考虑一个筐只有不多于一个球才有1的贡献代表什么。
很明显等效于有至少两个位置没有被匹配时有1的贡献。
进而可以构造如下模型:
每个筐拆成三个点,三个点之间相互连边。
对于球可以匹配某个筐,将球向筐的三个点都连边。
这样一来,如果有一个筐只有不多于一个点被匹配,那么剩下的两个点可以自己匹配增加答案。
如此最终结果是 $ ans-n $ 。
需要用到一般图最大匹配也即带花树。
由于答案要求输出匹配方案,所以要注意先匹配球再匹配筐。
#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
struct pat{int x,y;pat(int x=0,int y=0):x(x),y(y){}bool operator<(const pat &p)const{return x==p.x?y<p.y:x<p.x;}};
template<typename TP>inline void read(TP &tar)
{
	TP ret=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){ret=ret*10+(ch-'0');ch=getchar();}
	tar=ret*f;
}
namespace RKK
{
const int N=1011,M=300011;
struct sumireko{int to,ne;}e[M];int he[N],ecnt;
void addline(int f,int t){e[++ecnt].to=t;e[ecnt].ne=he[f],he[f]=ecnt;}
int n,m,o,tar[N];
int f[N];int find(int x){return f[x]==f[f[x]]?f[x]:f[x]=find(f[x]);}
int dep[N],da;
int pre[N],col[N];
queue<int>q;
int lca(int x,int y)
{
	da++;x=find(x),y=find(y);
	while(dep[x]!=da){dep[x]=da,x=find(pre[tar[x]]);if(y) swap(x,y);}
	return x;
}
void uno(int x,int y,int z)
{
	while(find(x)!=z)
	{
		pre[x]=y,y=tar[x];
		if(col[y]==2) col[y]=1,q.push(y);
		if(find(x)==x) f[x]=z;if(find(y)==y) f[y]=z;
		x=pre[y];
	}
}
int hun(int sp)
{
	memset(col,0,sizeof(col)),memset(pre,0,sizeof(pre));
	for(int i=1;i<=n+m*3;i++) f[i]=i;while(!q.empty()) q.pop();
	q.push(sp),col[sp]=1;
	while(!q.empty())
	{
		int x=q.front();q.pop();
		for(int i=he[x],t=e[i].to;i;i=e[i].ne,t=e[i].to)if(col[t]!=2&&find(x)!=find(t))
		{
			if(!col[t])
			{
				col[t]=2,pre[t]=x;
				if(!tar[t])
				{
					int lst=0;while(t) lst=tar[pre[t]],tar[t]=pre[t],tar[pre[t]]=t,t=lst;
					return 1;
				}else col[tar[t]]=1,q.push(tar[t]);
			}else{int z=lca(x,t);uno(x,t,z),uno(t,x,z);}
		}
	}
	return 0;
}
int main()
{
	int TAT;read(TAT);while(TAT--)
	{
		read(n),read(m),read(o);
		for(int i=1;i<=m;i++)
			addline(i,m+i),addline(m+i,i),addline(m+i,m*2+i),addline(m*2+i,m+i),addline(m*2+i,i),addline(i,m*2+i);
		for(int i=1,x,y;i<=o;i++)
			read(x),read(y),
			addline(m*3+x,y),addline(y,m*3+x),
			addline(m*3+x,m+y),addline(m+y,m*3+x),
			addline(m*3+x,m*2+y),addline(m*2+y,m*3+x);
		int ans=0;
		for(int i=m*3+1;i<=m*3+n;i++)if(!tar[i]) ans+=hun(i);
		for(int i=1;i<=m*3;i++)if(!tar[i]) ans+=hun(i);
		printf("%d\n",ans-n);
		for(int i=1;i<=n;i++) printf("%d ",(tar[m*3+i]-1)%m+1);putchar('\n');
		memset(he,0,sizeof(he)),ecnt=0,memset(dep,0,sizeof(dep)),da=0,memset(tar,0,sizeof(tar));
	}
	return 0;
}
}
int main(){return RKK::main();}
[WC2016]挑战NPC(一般图最大匹配)的更多相关文章
- [WC2016]挑战NPC
		Sol 这做法我是想不到\(TAT\) 每个筐子拆成三个相互连边 球向三个筐子连边 然后跑一般图最大匹配 这三个筐子间最多有一个匹配 那么显然每个球一定会放在一个筐子里,一定有一个匹配 如果筐子间有匹 ... 
- BZOJ 4405 [wc2016]挑战NPC 带花树 一般图最大匹配
		https://www.lydsy.com/JudgeOnline/problem.php?id=4405 这道题大概就是考场上想不出来,想出来也调不出来的题. 把每个桶拆成三个互相有边的点,每个球向 ... 
- [UOJ171][WC2016]挑战NPC
		uoj luogu bzoj sol 你可以列一个表格. 一个框子里放球的数量 0 1 2 3 对"半空框子"数量的贡献 1 1 0 0 把一个框子拆三个点.两两之间连边. 会发现 ... 
- [bzoj4405][wc2016]挑战NPC
		来自FallDream的博客,未经允许,请勿转载,谢谢. 小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样的题目: 有n个球,用整数1到n编号.还有m个筐子,用整数1到m编号. ... 
- [BZOJ]4405: [wc2016]挑战NPC(带花树)
		带花树模板 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; ... 
- 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/ ... 
随机推荐
- Solution -「Code+#4」「洛谷 P4370」组合数问题 2
			\(\mathcal{Description}\) Link. 给定 \(n,k\),求 \(0\le b\le a\le n\) 的 \(\binom{a}{b}\) 的前 \(k\) 大. ... 
- app内嵌H5网页(webviewJavaScriptBridge)
			摘要:使用的插件为webviewJavaScriptBridge,app端需要引入一下这个包,html页面只需一段JS代码 与IOS交互 <! 申明交互(此处代码固定) > functio ... 
- Dubbo源码剖析六之SPI扩展点的实现之getExtension
			上文Dubbo源码剖析六之SPI扩展点的实现之getExtensionLoader - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)中分析了getExtensionLoader,本文继续分 ... 
- CVE-2017-0213漏洞复现
			CVE-2017-0213漏洞形成的原因 类型混淆的漏洞通常可以通过内存损坏的方式来进行利用.然而漏洞发现者在利用时,并未采用内存损坏的方式来进行漏洞利用.按照漏洞发现者的说法,内存损坏的利用方式需要 ... 
- Golang 包管理机制
			Golang 包管理机制 1. 历史 在go1.11之前, 并没有官方的包管理机制(Godep算个半官方), 主流的包管理机制有: GoVendor Glide Godep 在go1.11之后, 官方 ... 
- Python:批量创建py文件
			import os filePrefix='Test' fileSuffix='.py' fileNum=7 #文件个数 for i in range(0,fileNum): filename=fil ... 
- ROS中msg和srv文件的区别
			1.msg和srv究竟有什么区别?? msg只是单向的发送和接受. srv包含两个部分:请求和响应. 2.msg和srv简介 msg:msg文件是描述ROS消息字段的简单文本文件.它们用于为不同语言( ... 
- qt(一)
			一.Qt安装 qt离线安装地址:http://download.qt.io/archive/qt/ 参考教程:https://blog.csdn.net/u013934107/article/deta ... 
- Spring框架第一天(搭建项目)
			Spring框架 1.简介 1.1 Spring是什么 一个开源的框架,是JavaEE开源框架 Spring是分层的 Java SE/EE应用 full-stack 轻量级开源框架,以IoC(Inve ... 
- iNeuOS工业互联网操作系统下发命令给iNeuLink硬件网关,进一步修改设备参数和控制设备
			目 录 1. 应用场景... 1 2. DCS数据采集... 2 3. 硬件网关的配置... 2 4. 平台端配置... 3 1. 应用场景 i ... 
