正题

题目链接:https://www.luogu.com.cn/problem/P4258


题目大意

给出\(n\)个球,\(m\)个篮筐,每个球都可以被放入一些特定的篮筐,每个球都要放,要求球的个数小于等于\(1\)的篮筐数量最多。

保证有解,输出方案。

\(1\leq T\leq 5,1\leq n\leq 3m,1\leq m\leq 100\)


解题思路

额其实做题之前已经知道正解是带花树就简单很多了。

每个篮筐我们开一个三个点的环,那么如果环上大于一个点呗匹配掉了那么这个环内就无法匹配了。

又因为一定有解所以肯定不会因为环上的匹配使答案更劣,所以这样匹配出来的结果为\(ans\)那么答案就是\(ans-n\)。

但是有一个问题我们发现这样跑的话每个球不一定都是匹配点,这样会影响我们输出方案。因为我们是找增广路的做法,这种做法不会减少已经匹配了的点,所以我们如果优先跑球代表的点就不会有问题了。


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1010,M=2e5+10;
struct node{
int to,next;
}a[M<<1];
int cnt,tot,T,n,m,e,ans,ls[N];
int dfn[N],pre[N],fa[N],match[N],tag[N];
queue<int> q;
void addl(int x,int y){
a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;
a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;
return;
}
int find(int x)
{return (fa[x]==x)?(x):(fa[x]=find(fa[x]));}
int LCA(int x,int y){
++cnt;x=find(x);y=find(y);
while(dfn[x]!=cnt){
dfn[x]=cnt;
x=find(pre[match[x]]);
if(y)swap(x,y);
}
return x;
}
void Blossom(int x,int y,int lca){
while(find(x)!=lca){
pre[x]=y;y=match[x];
if(tag[y]==2){tag[y]=1;q.push(y);}
fa[x]=fa[y]=lca;x=pre[y];
}
return;
}
int Agu(int s){
memset(tag,0,sizeof(tag));
memset(pre,0,sizeof(pre));
for(int i=1;i<=3*m+n;i++)fa[i]=i;
while(!q.empty())q.pop();
q.push(s);tag[s]=1;
while(!q.empty()){
int x=q.front();q.pop();
for(int i=ls[x];i;i=a[i].next){
int y=a[i].to;
if(!tag[y]){
tag[y]=2;pre[y]=x;
if(!match[y]){
for(int u=y,lst;u;u=lst)
lst=match[pre[u]],match[u]=pre[u],match[pre[u]]=u;
return 1;
}
tag[match[y]]=1;q.push(match[y]);
}
else if(tag[y]==1&&find(x)!=find(y)){
int lca=LCA(x,y);
Blossom(x,y,lca);
Blossom(y,x,lca);
}
}
}
return 0;
}
int main()
{
scanf("%d",&T);
while(T--){
tot=ans=0;
memset(ls,0,sizeof(ls));
memset(match,0,sizeof(match));
scanf("%d%d%d",&n,&m,&e);
for(int i=1;i<=m;i++)
addl(i*3-2,i*3-1),addl(i*3-1,i*3),addl(i*3,i*3-2);
for(int i=1;i<=e;i++){
int x,y;
scanf("%d%d",&x,&y);
addl(x+3*m,y*3);
addl(x+3*m,y*3-1);
addl(x+3*m,y*3-2);
}
for(int i=n+3*m;i>=1;i--)
if(!match[i])ans+=Agu(i);
printf("%d\n",ans-n);
for(int i=1;i<=n;i++)
printf("%d ",1+(match[3*m+i]-1)/3);
putchar('\n');
}
return 0;
}

P4258-[WC2016]挑战NPC【带花树】的更多相关文章

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

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

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

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

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

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

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

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

  5. [bzoj4405][wc2016]挑战NPC

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

  6. [WC2016]挑战NPC

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

  7. [UOJ171][WC2016]挑战NPC

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

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

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

  9. 「WC2016」挑战NPC

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

随机推荐

  1. h5与小程序互相跳转,传参和获取参数

    1.h5跳转到小程序 首先引入js文件 <script src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js">< ...

  2. flutter查看安全码SHA1

    最近flutter技术调研高德地图插件时,要用到安全码,可以打开cmd,键入一下命令查看.(注意路径用户名yourusernamehere改为自己的) keytool -list -v -keysto ...

  3. 一些Java知识点

    1 import java.util.ArrayList; 2 3 public class Main { 4 5 public static void main(String[] args) { 6 ...

  4. OVN入门

    参考链接 如何借助 OVN 来提高 OVS 在云计算环境中的性能 OVN简介 Open vSwitch Documentation OVSDB介绍及在OpenDaylight中的调用 OpenDayl ...

  5. mycat<三>

    server.xml文件 <?xml version="1.0" encoding="UTF-8"?> <!-- - - Licensed u ...

  6. roslaunch保存的log文件没有打印的ERROR信息

    最近调试,发现roslaunch启动的节点,log文件中没有ERROR信息. 经过一番查证发现,INFO和WARN是保存在log文件中,ERROR直接打印在terminal 参考: https://g ...

  7. Qt5完美解决 界面显示中文乱码

    最近在学习Qt,可是一直头疼于中文乱码问题,上网搜了一下,很多都是Qt4中使用如下方法: QTextCodec *codec = QTextCodec::codecForName("gbk& ...

  8. idea快速搭建Tomcat服务器

    创建Web项目 新建Classes和lib文件夹 配置输出路径和资源路径 快捷键ctr+shift+alt+S打开项目配置 在modules下修改输出路径 修改依赖目录 修改war包输出路径 新建to ...

  9. 问题:idea 中文无法使用

    1. 问题--idea无法使用中文输入 原因:idea本身版本过高,所以需要你强制减低它的jdk版本 解决:使用配置idea环境变量解决  ps:目前适用于任何版本的jdk和idea 步骤: 1.新建 ...

  10. viper配置管理

    安装 go get github.com/spf13/viper viper支持的功能 1.可以设置默认值 2.可以加载多种格式的配置文件,如JSON,TOML,YAML,HCL和Java属性配置文件 ...