给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. TCAM 与CAM

    CAM是Content Addressable Memory的缩写,即"内容寻址存储器"的意思,它是在传统的存储技术的基础上实现的联想记忆存储器,关于CAM的基本操作有三种: 1) ...

  2. 重新部署mysql遇到的问题

    Windows 2008 Server R2 MySql: 5.7 下载Mysql. 配置mysql环境变量 注册mysql服务.(mysqld install) 移除注册,sc delete mys ...

  3. 字符串循环右移-c语言

    一个长度为len的字符串,对其循环右移n位 [期望]char str[] = "abcdefg";右移3次后,变成"efgabcd" [思路] 思路1. 如果用 ...

  4. Debian9镜像安装问题

    Debian9下载地址 https://www.debian.org/distrib/ Debian9有三个镜像文件 第一个包含系统2.3两个主要是一些软件的安装包只需下载第一个安装系统即可 默认安装 ...

  5. Sql Server数据库对象访问权限控制

    以下内容主要针对database层面的数据访问权限(比如select, insert, update, delete, execute…) 1.直接给user权限GRANT EXECUTE TO [u ...

  6. vue跨域解决及打包

    打包之前需要修改如下配置文件: 配置文件一:build>>>utils.js (修改publicPath:"../../" , 这样写是处理打包后找不到静态文件( ...

  7. ubuntu破解密码方法

    摘要: 开机按住任何键(shift)停住grub菜单,进入advanced option for ubuntu,出现的菜单中,光标移动至…(recovery mode)按E进入编辑,找到ro reco ...

  8. php用面向对象从mysql取数据

    <?php //建立数据库的链接@$_mysqli = new mysqli('localhost','root','123456','dbname');if(mysqli_connect_er ...

  9. html文本溢出显示省略字符的两种常用方法

    方法一:使用CSS溢出省略的方式解决 解决效果如下: css代码: display: -webkit-box; display: -moz-box; white-space: pre-wrap; wo ...

  10. 大数据开发学习之构建Hadoop集群-(0)

    有多种方式来获取hadoop集群,包括从其他人获取或是自行搭建专属集群,抑或是从Cloudera Manager 或apach ambari等管理工具来构建hadoop集群等,但是由自己搭建则可以了解 ...