给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关于集合的几种变量方式

    package com.java.test; import java.util.ArrayList;import java.util.Enumeration;import java.util.Iter ...

  2. SQL Server 2008还原数据库的具体方法

    俗话说“好记性不如烂笔头”,在相隔较长的时间段内,每次还原客户的数据库都记不清完全的步骤,为此mark一下. SQL Server 2008一般默认备份的文件格式是bak,即后缀名为.bak.bak文 ...

  3. ios 根据颜色生成图片,十六进制颜色。

    //颜色生成图片方法 - (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size { CGRect rect = CGRectMake ...

  4. dataTables去掉搜索框和每页多少条框体,解决Cannot reinitialise DataTable问题

    $('#example').DataTable({ searching:false, //去掉搜索框 bLengthChange:false,//去掉每页多少条框体 "language&qu ...

  5. ssm框架搭建(上)

    前言 之前也说过,工作做的开发都是基于公司现有的框架,心里很没底.所以一直想自己能够搭建出ssm框架.经过多次尝试,终于成功了.这边文章将从两个方面进行,一是框架搭建,二是简单的增删查改. 正文 1. ...

  6. 基于SAE的Python+Django部署

    本文主要参考:http://www.cnblogs.com/qtsharp/archive/2012/01/12/2320774.html,另外包括自己的实际操作. 一.申请SAE帐号以及创建应用ya ...

  7. Android(java)学习笔记168:Activity 4 种启动模式

    1. 任务栈(task stack): 任务栈 是用来记录用户操作的行为,维护一个用户体验. 一个应用程序一般都是由多个activity组成的. 任务栈(task stack)记录存放用户开启的act ...

  8. Qt 之 QApplication

    1.QApplication QApplication类管理GUI程序的控制流和主要设置,是基于QWidget的,为此特化了QGuiApplication的一些功能,处理QWidget特有的初始化和结 ...

  9. 最短路 || POJ 2387 Til the Cows Come Home

    从点N到1的最短路 *记得无向图两个方向都要建边就好了…… 以及多组数据= = #include <iostream> #include <cstdio> #include & ...

  10. linux(Ubuntu/Centos) iproute 路由IP地址等命令集合,查看端口链接

    原 linux(Ubuntu/Centos) iproute 路由IP地址等命令集合,查看端口链接 2017年03月20日 16:55:57 风来了- 阅读数:2291 标签: centoslinux ...