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

Luogu

题解时间

思路十分有趣。

考虑一个筐只有不多于一个球才有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(一般图最大匹配)的更多相关文章

  1. [WC2016]挑战NPC

    Sol 这做法我是想不到\(TAT\) 每个筐子拆成三个相互连边 球向三个筐子连边 然后跑一般图最大匹配 这三个筐子间最多有一个匹配 那么显然每个球一定会放在一个筐子里,一定有一个匹配 如果筐子间有匹 ...

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

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

  3. [UOJ171][WC2016]挑战NPC

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

  4. [bzoj4405][wc2016]挑战NPC

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

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

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

  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. linux大工程 - 我要一个属于自己的回收站

    我要开始装13了 'rm -rf 是一个很"粗鲁"的命令,就像windows的shift+delete,删除的文件是无法找回的(当然,除了数据恢复软件,但是很麻烦,很费时)' '为 ...

  2. jmeter之jsonpath和beanshell联合使用

    目的 下面返回的json字符串中,提取args的值中,最后一个逗号后面的字符串,比如下面就是提取:woLgrKts5s9Q4huajoCGHS {"code":20000,&quo ...

  3. 【用户状态】详细解读Oracle用户ACCOUNT_STATUS的九种状态

    转至:http://blog.itpub.net/519536/viewspace-672276/ DBA_USERS视图中ACCOUNT_STATUS记录的用户的当前状态,一般情况下在使用的正常用户 ...

  4. SpringMVC教程--Idea中使用Maven创建SpringMVC项目

    1.新建项目 参照idea教程中的创建maven项目https://www.cnblogs.com/daxiang2008/p/9061653.html 2.POM中加入依赖包 (1)指定版本 (2) ...

  5. 根据文件url,下载文件到本地

    /// <summary> /// 根据文件url,下载文件到本地 /// </summary> /// <param name="fileUrl"& ...

  6. JAVA的对象和封装及static与final的用法(详解)

    一:软件出现的目的 1:用计算机的语言描述现实世界 2:用计算机解决现实世界的问题 编程思维:  使用面向对象的思想(描述)面向对象的世界     (符合人类的思维习惯) 二:面向对象设计和开发程序的 ...

  7. 反压缩 js ,我的万花筒写轮眼开了,CV 能力大幅提升

    前言 因为比较菜,所以经常需要读一些别人的代码学习学习. 有源码的代码当然好,但是很多网站不开源.这些网站的 js 又都是打包压缩过的,学习起来很难受. 所以我做了一个小工具,通过修改抽象语法树,来处 ...

  8. JAVA String、StringBuilder、和StringBuffer的区别,及如何使用

    目录 String类 一.String类的理解和创建对象 二.String类创建的方式 两种创建String对象的区别 测试题 三.String常用方法 四.StringBuffer类 1.Strin ...

  9. 动手学TCP——CS144实验感想

    在Stanford CS144的课程实验Lab0~Lab4中,我们动手实现了一个自己的TCP协议,并且能够真的与互联网通信!此外,感谢Stanford开源本实验并提供了大量的优质测试用例,使得我们仅仅 ...

  10. GPT-3被超越?解读低能耗、高性能的GlaM模型

    原创作者 | LJ GLaM: Efficient Scaling of Language Models with Mixture-of-Experts https://arxiv.org/pdf/2 ...