给n<=100000个点的树,每个点有一个01串,长度m<=200,串的可以随时01取反,串的每一位对应权Vi,从根节点到某个节点经过决定哪些串取反后取得的最大价值为某个点的权值,求:在这棵树上乱走,不能走权相同的相邻两点,每个长度D的简单路径的方案数。

题目很奇怪。结论很不显然。TJM和HR大佬很强。

首先,最后遍历的树的深度不会超过logm。在树上每走一步,都可以把0的个数减少至少一半。

其次,未达到最大值的两个点权值肯定不同。道理同上。因此把目标转化为“在权值未满的树上走”,重点在如何找出这棵树。

再者,Mi表示属性i的选择情况,在n个串中,当且仅当所有的Mi取遍2^n种集合时没有最优方案,最优方案即所有属性都取得到。在这m个选择情况中若取遍2^n种集合,则有全为0的Mi,必须把它某一位对应的串取反,但这意味着那个“只有这一位为0的选择情况”不合法,我们要选另一位,这样一直搞下去,所有的串都取反了,那那些全为1的Mi就gg了。

最后,在n个串中,若Mi没取遍2^n种集合,一定可以构造出最优方案。方法即把不存在的某个选择情况的1的位取反。这时除非某个选择情况与不存在的那种完全相同,否则必然会有一位为1。

于是,两次dfs解决。第二次dfs的统计方案易错,注意一下。

 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<math.h>
//#include<iostream>
using namespace std; int n,m;
#define maxn 100011
char s[];bool mp[maxn][];
struct Edge{int to,next;};
int vis[],state[];
#define LL long long
LL dis[][],ans[];
struct Tree
{
Edge edge[maxn<<];
int first[maxn],le;
Tree() {le=;}
void in(int x,int y)
{
edge[le].to=y;
edge[le].next=first[x];
first[x]=le++;
}
void dfsfirst(int x,int dep)
{
int tot=(<<dep);
for (int i=;i<=m;i++)
{
if (mp[x][i]) state[i]|=<<(dep-);
if (vis[state[i]]!=x) tot--,vis[state[i]]=x;
}
if (tot) first[x]=;
for (int i=first[x];i;i=edge[i].next)
dfsfirst(edge[i].to,dep+);
for (int i=;i<=m;i++)
if (mp[x][i]) state[i]^=<<(dep-);
}
void dfsfirst()
{
memset(vis,,sizeof(vis));
dfsfirst(,);
}
void dfssec(int x,int dep)
{
memset(dis[dep],,sizeof(dis[dep]));
dis[dep][]=dis[dep][]=;
for (int i=first[x];i;i=edge[i].next)
{
dfssec(edge[i].to,dep+);
for (int j=dep+;j<=;j++)
for (int k=dep+;k<=;k++)
ans[j+k-dep-dep]+=dis[dep][j-dep]*dis[dep+][k-dep];
for (int j=;j<=-dep-dep;j++) dis[dep][j+]+=dis[dep+][j];
}
}
void dfssec() {dfssec(,);}
}t;
int x;
int main()
{
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++)
{
scanf("%s",s);
for (int j=;j<m;j++) mp[i][j+]=s[j]-'';
}
for (int i=;i<=m;i++) scanf("%d",&x);
for (int i=;i<=n;i++) scanf("%d",&x),t.in(x,i);
t.dfsfirst();
memset(ans,,sizeof(ans));
t.dfssec();
int i;
for (i=;i>=;i--) if (ans[i]) break;
printf("%d ",n);
for (int j=;j<=i;j++) printf("%lld ",ans[j]);
return ;
}

汕头市赛srm1X T3的更多相关文章

  1. 汕头市队赛SRM14 T3覆盖

    我们可以考虑两种情况 区间之间不相重叠 和 重叠 f[i][j]表示以当前最后一个区间以 i 结尾 并且选了 j 个区间 不相重叠的话 只要选 1-i-w 的max再加上 包含i在内的前四个数的和 相 ...

  2. 汕头市队赛 SRM13 T3

    这道题可以贪心 维护一个答案队列 枚举位置 每次将比当前位置大的队尾全部替代掉 记录删了多少了就好了 #include<cstdio> #include<iostream> # ...

  3. 汕头市队赛 SRM1X T2 ——扫描线

    绵津见-终 SRM 13 背景 “西瓜也是可以种在海上的!”——绵津见 然而种在海上的西瓜最需要防范的,是时不时会涌向瓜田的阵阵海浪. 幸好,身为海神的绵津见可以释放魔法“水平如镜”来阻止海浪拍打西瓜 ...

  4. 汕头市队赛 SRM1X T1

    木之本樱 背景 “西瓜是可以种在树上的!”——木之本樱 描述 空地上,一排排的西瓜树拔地而起. 魔法世界里,空地是无限大的.所有的树排成了n条直线,每条直线也是向左右两端无限延伸的. 由于自己姓木(之 ...

  5. 汕头市队赛 SRM10 T3 数学上来先打表

    数学上来先打表 SRM 10 描述 给出 n个点(不同点之间有区别),求出满足下列条件的连边(双向边)方案:1.每条边连接两个不同的点,每两个点之间至多有一条边2.不存在三个点a,b,c使三个点间两两 ...

  6. 洛谷noip 模拟赛 day1 T3

    T7983 大芳的逆行板载 题目背景 大芳有一个不太好的习惯:在车里养青蛙.青蛙在一个n厘米(11n毫米s)的Van♂杆子上跳来跳去.她时常盯着青蛙看,以至于突然逆行不得不开始躲交叉弹.有一天他突发奇 ...

  7. 「2018-12-02模拟赛」T3 约束排列 解题报告

    3.约束排列(place.pas/cpp/in/out) 问题描述: 给出 n 个互不相同的小写字母,表示出现的字符类型,以及 k 个约束关系: .....,表示 ai 必须出现在 bi 前面(ai, ...

  8. 雅礼 noip2018 模拟赛 day3 T3

    典型树形dp 这里,我们应该看到一些基本性质: ①:如果这个边不能改(不是没有必要改),我们就不改,因为就算改过去还要改回来,显然不是最优的 注意:"不能改"是指边的性质和要求的相 ...

  9. war2 洛谷模拟赛day2 t3 状压

    (new )   war2 题解:总体数据而言,我们很容易想到着就是DP啊,我们DP数组,用状态压缩,代表有那些点已经被占领过了,代表上一次我占的是那个.对于每一次状态转移,若当前我们要占领的Port ...

随机推荐

  1. AJPFX总结方法里的属性

    嵌套循环:循环里套循环 假设外循环的循环次数是m次,内循环的循环次数是n次,那么内层循环的循环次数需要 m * n次.   Eg:利用for循环语句的嵌套打印出乘法口诀表   class break1 ...

  2. C++模板类头文件和实现文件分离

    http://www.cnblogs.com/lvdongjie/p/4288373.html 如何实现C++模板类头文件和实现文件分离,这个问题和编译器有关. 引用<<C++primer ...

  3. mysql 查询数据库参数命令

    1.select @@tx_isolation;    查询数据库设置的事务隔离级别 2.desc table_name;  显示表设计 3.show create table table_name; ...

  4. General mistakes in parallel computing

    这是2013年写的一篇旧文,放在gegahost.net上面  http://raison.gegahost.net/?p=97 March 11, 2013 General mistakes in ...

  5. UVA 11346 Probability 概率 (连续概率)

    题意:给出a和b,表示在直角坐标系上的x=[-a,a] 和 y=[-b,b]的这样一块矩形区域.给出一个数s,问在矩形内随机选择一个点p=(x,y),则(0.0)和p点组成的矩形面积大于s的概率是多少 ...

  6. mysql-mmm 部署高可用集群

    集群的部署(mysql-mmm + 主从同步) 什么是集群? 多台服务器提供相同的服务 集群的好处? 节省成本. 配置集群? 准备环境:准备4台数据库服务器 准备服务器,能够ping 4 台数据库服务 ...

  7. web测试需要注意点

  8. Python 中print 和return 的区别

    1.print() print()函数的作用是输出数据到控制台,就是打印在你能看到的界面上. 2.return return语句[表达式]退出函数,选择性地向调用方返回一个表达式.不带参数值的retu ...

  9. javaweb系列-关于HttpSessionListener的sessionDestroyed什么时候触发

    根据书本写了下面这个监听器,然后开始调试,打开一个浏览器来访问该网页,可以正常触发sessionCreated,然后关闭浏览器,发现没有触发sessionDestroyed,然后我怀疑是不是这个监听器 ...

  10. 基于VueJS的render渲染函数结合自定义组件打造一款非常强大的IView 的Table

    基于VueJS的render渲染函数结合自定义组件打造一款非常强大的IView 的Table https://segmentfault.com/a/1190000015970367