正题

题目链接: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. Thread类中yield方法

    Yield方法可以暂停当前正在执行的线程对象,让其他有相同优先级的线程执行.它是一个静态方法而且只保证当前线程放弃CPU占用而不能保证其它线程一定能占用CPU,执行yield()的线程有可能在进入到暂 ...

  2. SQL查询对分数进行排名

    编写SQL查询以对分数进行排名. 如果两个分数之间存在平局,则两者应具有相同的排名. 请注意,在平局之后,下一个排名数应该是下一个连续的整数值. 换句话说,等级之间不应该存在"漏洞" ...

  3. Java常用类之字符串类

    String 的特性 public final class String implements java.io.Serializable, Comparable<String>, Char ...

  4. C#与.NET、CLR、CLI是什么关系?什么是.NET框架

    1.C#与.NET.CLR.CLI是什么关系?什么是.NET框架?      这个问题好专业啊!一句话两句话还真不好说清.您听说过C++中有个COM的概念吧?您听说过JAVA里的虚拟机吧?CLR(公共 ...

  5. Java File常见用法

    一.构造方法 File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的 File实例. File(String pathname) 通过将给定的路径名字符 ...

  6. 转:JAVA 参数传递

    转自:http://blog.sina.com.cn/s/blog_5dd380b90100bvel.html 网络上有太多关于JAVA参数传递是传值还是传引用的讨论,其实大多是概念不清,混淆视听.从 ...

  7. 刷题-力扣-213. 打家劫舍 II

    213. 打家劫舍 II 题目链接 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/house-robber-ii/ 著作权归领扣网络所有.商业 ...

  8. OpenCV 生成矩形mask

    生成mask的一种操作 cv::Mat mask = cv::Mat::zeros(300, 300, CV_8UC1); mask(cv::Rect(100,150,100, 50)) = 255; ...

  9. Appium问题解决方案(3)- java.lang.IllegalStateException: UiAutomation not connected!

    背景 连着手机,运行脚本,一段时间之后就报错了,看了Appium-server,发现报了这样一个错误 如何解决呢? 步骤一 通过 adb devices ,确定设备是否已连接上 步骤二(最终解决方案) ...

  10. Linux常用命令 - tail命令详解

    21篇测试必备的Linux常用命令,每天敲一篇,每次敲三遍,每月一循环,全都可记住!! https://www.cnblogs.com/poloyy/category/1672457.html 实时刷 ...