题目描述

$Treeland$国有$n$座城市,其中$1$号城市是首都,这些城市被一些单向高铁线路相连,对于城市$i\neq 1$,有一条线路从$i$到$p_i(p_i<i)$。每条线路都是一样长的,通过花费时间也是一样长的。
这个国家的每一个城市都有一种特产,整个国家有$m$种特产(不同城市可能又相同的特产),其中城市$i$的特产用$a_i$表示。
小$C$和他的几位$A$队爷朋友(总共$c$人,$2\leqslant c\leqslant 5$)正在$Treeland$国游玩,他们准备在一个城市进行$water party$。召开$party$的城市必须满足每个人从各自城市出发能尽快到齐。注意可能有人在同一个城市。
小$C$和他的朋友们准备各自带一些特产到$party$。这些特产必须满足以下条件:
    $\alpha.$每个人带的特产数量必须相同。
    $\beta.party$里不能够有任何两种相同的特产。
    $\gamma.$每个人只能带他所经过的城市的特产。
对于每个询问,计算出$party$中最多有多少种特产。


输入格式

第一行三个整数$n,m,q$,分别表示城市个数,特产种数,询问个数。
第二行有$n-1$个整数,表示$p_1,p_2,p_3,...,p_n$。
第三行有$n$个整数,表示$a_1,a_2,...,a_n$。
接下来$q$行,每行表示一个询问。每个询问第一个整数$c$表示人数,接下来有$c$个整数表示每一个人所在城市的编号。


输出格式

对于每个询问输出一行一个整数,表示答案。


样例

样例输入:

5 3 4
1 2 2 1
2 3 1 3 1
2 3 4
3 5 2 2
4 3 4 2 5
2 2 2

样例输出:

2
3
0
0


数据范围与提示

对于$100\%$的数据,满足:

$2\leqslant n\leqslant 300,000,1\leqslant m\leqslant 1,000,0\leqslant q\leqslant 50,000,1\leqslant p_i<i,1\leqslant a_i\leqslant m,2\leqslant c\leqslant 5$。


题解

延续上道题的思路,发现最多只有$5$个人,接着考虑网络流问题。

容易(我不容易)发现,从源点给每个人连一定容量的边(容量利用二分即可),每个人向他的颜色连边,颜色再向汇点连容量为$1$的边,能跑满则可行,求最小割即可。

接着运用霍尔定理简化问题,二分将城市拆成多少个点,然后看是否有完美匹配即可。

可以用$bitset+$树链剖分获取集合。

时间复杂度:$\Theta(\frac{n\log n\times m}{w})$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. struct rec{int nxt,to,w;}e[300000];
  4. int head[300001],cnt=1;
  5. int fa[300001];
  6. int n,m,q;
  7. int a[300001];
  8. int depth[300001],son[300001],size[300001],dfn[300001],wzc[300001],topp[300001];
  9. int c[50001][10];
  10. bitset<1024> bit1[300001],bit2[600001];
  11. void add(int x,int y)
  12. {
  13. e[++cnt].nxt=head[x];
  14. e[cnt].to=y;
  15. head[x]=cnt;
  16. }
  17. void dfs1(int x)
  18. {
  19. depth[x]=depth[fa[x]]+1;
  20. size[x]=1;
  21. for(int i=head[x];i;i=e[i].nxt)
  22. {
  23. dfs1(e[i].to);
  24. size[x]+=size[e[i].to];
  25. if(!son[x]||size[e[i].to]>=size[son[x]])
  26. son[x]=e[i].to;
  27. }
  28. }
  29. void dfs2(int x,int tp)
  30. {
  31. dfn[x]=++cnt;
  32. wzc[cnt]=x;
  33. if(!tp)tp=x;
  34. topp[x]=tp;
  35. if(son[x])dfs2(son[x],tp);
  36. for(int i=head[x];i;i=e[i].nxt)
  37. if(e[i].to!=son[x])dfs2(e[i].to,0);
  38. }
  39. void dfs3(int x)
  40. {
  41. if(x==topp[x])bit1[x].set(a[x]);
  42. else (bit1[x]=bit1[fa[x]]).set(a[x]);
  43. for(int i=head[x];i;i=e[i].nxt)
  44. dfs3(e[i].to);
  45. }
  46. int LCA(int x,int y)
  47. {
  48. while(topp[x]!=topp[y])
  49. {
  50. if(depth[topp[x]]<depth[topp[y]])swap(x,y);
  51. x=fa[topp[x]];
  52. }
  53. return depth[x]<depth[y]?x:y;
  54. }
  55. void build(int l,int r)
  56. {
  57. if(l==r)
  58. {
  59. bit2[(l+r)|(l!=r)].set(a[wzc[l]]);
  60. return;
  61. }
  62. int mid=(l+r)>>1;
  63. build(l,mid);
  64. build(mid+1,r);
  65. bit2[(l+r)|(l!=r)]=bit2[(l+mid)|(l!=mid)]|bit2[(mid+1+r)|(mid+1!=r)];
  66. }
  67. bitset<1024> ask(int l,int r,int L,int R)
  68. {
  69. if(L<=l&&r<=R)return bit2[(l+r)|(l!=r)];
  70. int mid=(l+r)>>1;
  71. bitset<1024> res;
  72. if(L<=mid)res|=ask(l,mid,L,R);
  73. if(R>mid) res|=ask(mid+1,r,L,R);
  74. return res;
  75. }
  76. bitset<1024> query(int x,int lca)
  77. {
  78. bitset<1024> res;
  79. while(topp[x]!=topp[lca])
  80. {
  81. res|=bit1[x];
  82. x=fa[topp[x]];
  83. }
  84. res|=ask(1,n,dfn[lca],dfn[x]);
  85. return res;
  86. }
  87. int main()
  88. {
  89. scanf("%d%d%d",&n,&m,&q);
  90. for(int i=2;i<=n;i++)
  91. {
  92. int x;
  93. scanf("%d",&x);
  94. add(x,i);
  95. fa[i]=x;
  96. }
  97. for(int i=1;i<=n;i++)scanf("%d",&a[i]);
  98. cnt=0;
  99. dfs1(1);
  100. dfs2(1,0);
  101. for(int i=1;i<=q;i++)
  102. {
  103. scanf("%d",&c[i][0]);
  104. for(int j=1;j<=c[i][0];j++)
  105. scanf("%d",&c[i][j]);
  106. }
  107. dfs3(1);
  108. build(1,n);
  109. for(int i=1;i<=q;i++)
  110. {
  111. bitset<1024> set[10];
  112. int lca=LCA(c[i][1],c[i][2]);
  113. for(int j=3;j<=c[i][0];j++)lca=LCA(lca,c[i][j]);
  114. for(int j=1;j<=c[i][0];j++)
  115. set[j]=query(c[i][j],lca);
  116. int ans=m;
  117. for(int s=1;s<(1<<c[i][0]);s++)
  118. {
  119. int cnt=0;
  120. set[0].reset();
  121. for(int j=0;j<c[i][0];j++)
  122. if(s&(1<<j))
  123. {
  124. set[0]|=set[j+1];
  125. cnt++;
  126. }
  127. ans=min(ans,(int)set[0].count()/cnt);
  128. }
  129. printf("%d\n",ans*c[i][0]);
  130. }
  131. return 0;
  132. }

rp++

[CSP-S模拟测试]:party?(霍尔定理+最小割+树链剖分)的更多相关文章

  1. [CSP-S模拟测试]:weight(Kruskal+树链剖分)

    题目描述 给你一个$n$个点$m$条边的带边权的无向图(无重边,无自环),现在对于每条边,问你这条边的权值最大可以是多大,使得这条边在无向图的所有最小生成树中?(边权都是整数). 输入格式 第一行包含 ...

  2. 【BZOJ-4435】Juice Junctions 最小割树(分治+最小割)+Hash

    4435: [Cerc2015]Juice Junctions Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 20  Solved: 11[Submi ...

  3. 【BZOJ-2229】最小割 最小割树(最大流+分治)

    2229: [Zjoi2011]最小割 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 1565  Solved: 560[Submit][Status ...

  4. BZOJ2040[2009国家集训队]拯救Protoss的故乡——模拟费用流+线段树+树链剖分

    题目描述 在星历2012年,星灵英雄Zeratul预测到他所在的Aiur行星在M天后会发生持续性暴雨灾害,尤其是他们的首都.而Zeratul作为星灵族的英雄,当然是要尽自己最大的努力帮助星灵族渡过这场 ...

  5. BZOJ2229: [Zjoi2011]最小割(最小割树)

    传送门 最小割树 算法 初始时把所有点放在一个集合 从中任选两个点出来跑原图中的最小割 然后按照 \(s\) 集合与 \(t\) 集合的归属把当前集合划分成两个集合,递归处理 这样一共跑了 \(n − ...

  6. 最小割树(Gomory-Hu Tree)求无向图最小割详解 附 BZOJ2229,BZOJ4519题解

    最小割树(Gomory-Hu Tree) 前置知识 Gomory-Hu Tree是用来解决无向图最小割的问题的,所以我们需要了解无向图最小割的定义 和有向图类似,无向图上两点(x,y)的割定义为一个边 ...

  7. [学习笔记]最小割树(Gomory-Hu Tree)

    最小割树(\(\mathcal{Gomory-Hu Tree}\))简明指南 对于单源最短路径,我们有\(SPFA\)和\(Dijkstra\),对于多源最短路径,我们有\(Floyd\):对于两点间 ...

  8. [洛谷]P3729 曼哈顿计划EX(最小割树/等价流树)

    题目大意:给出一张n个点m条边的无向图,每个点有点权,q次询问,每次给出k,要求选出若干个点点权之和不小于k,求一个最大的值x,使得选出的点中任意两点之间至少有x条互不相交的链.(n<=550, ...

  9. BZOJ4519[Cqoi2016]不同的最小割——最小割树+map

    题目描述 学过图论的同学都知道最小割的概念:对于一个图,某个对图中结点的划分将图中所有结点分成 两个部分,如果结点s,t不在同一个部分中,则称这个划分是关于s,t的割.对于带权图来说,将 所有顶点处在 ...

随机推荐

  1. springboot连接mysql报错:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException

    nested exception is org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. ...

  2. Python自学第二天学习之《字符串与数字》

    一.基本数据类型: 数字:int类型,不可变类型 格式 : a=10 1.其他类型转换成int型 : b=“123” c=int(b) #转换类型 print(c)----- 123 print(ty ...

  3. ZOJ 2706 Thermal Death of the Universe

    Thermal Death of the Universe Time Limit: 10 Seconds                                     Memory Limi ...

  4. cocos2d-x 3.0正式版创建project笔记

    cocos2d-x 3.0正式版创建project笔记     不知道Beta版那个高大上的对话框哪里去鸟,正式版又回归到命令行,不知道触碰如此频繁的玩弄追随者的编程习惯是出于什么心理,假设不是为了这 ...

  5. git 命令图解

    git 命令图解   初始化版本库 git config user.name "lsgx" git config user.email "lsgxthink@163.co ...

  6. vue + element 创建教程

    一.环境准备 node安装 node版本:v10.15.3 node下载地址:https://nodejs.org/zh-cn/ vue-cli安装 全局安装vue-cli npm install - ...

  7. #import,#include与@class的区别

    1.#include是C中用来引用文件的关键字,而#import是obj-c中用来代替include的关键字.#import可以确保同一个文件只能被导入一次,从而避免了使用#include容易引起的重 ...

  8. setter getter 方法

    MRC下setter.getter方法写法.重写dealloc方法 @interface People : NSObject @property (nonatomic,strong) NSString ...

  9. 【记录】使用Navicat将表设计导出数据库设计文档

    INFORMATION_SCHEMA. Tables -- 表信息 INFORMATION_SCHEMA. COLUMNS -- 列信息 参考文章地址:https://blog.csdn.net/cx ...

  10. samba - 为 UNIX 实现的 Windows SMB/CIFS 文件服务器

    SYNOPSIS 总览 Samba DESCRIPTION 描述 samba 套件是在 UNIX 系统上实现“服务器信息块”(通常简称 SMB) 协议的一组程序.这个协议有时也称为“通用互联网文件系统 ...