博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
小奇的仓库(树形DP)
阅读量:4646 次
发布时间:2019-06-09

本文共 4203 字,大约阅读时间需要 14 分钟。

「题目背景」

小奇采的矿实在太多了,它准备在喵星系建个矿石仓库。令它无语的是,喵星系的货运飞船引擎还停留在上元时代!

「问题描述」

喵星系有n个星球,星球以及星球间的航线形成一棵树。

从星球a到星球b要花费[dis(a,b) Xor M]秒。(dis(a,b)表示ab间的航线长度,Xor为位运算中的异或)

为了给仓库选址,小奇想知道,星球i(1<=i<=n)到其它所有星球花费的时间之和。

「输入格式」

第一行包含两个正整数n,M。

接下来n-1行,每行3个正整数a,b,c,表示a,b之间的航线长度为c。

「输出格式」

n行,每行一个整数,表示星球i到其它所有星球花费的时间之和。

「样例输入」

4 0

1 2 1

1 3 2

1 4 3

「样例输出」

6

8

10

12

「数据范围」

序号   N    M

 1    6    0

 2   100   5

 3  2000   9

 4  50000  0

 5  50000  0

 6  50000  1

 7  50000  6

 8  100000 10

 9  100000 13

 10 100000 15

保证答案不超过2*10^9

下面一段话是出题人神秘而不失优雅的题解

算法1:

不会写函数的小伙伴们,我们只需要写个floyd,就有10分啦!

算法2:

在算法1的基础上,我们对每条边处理一下xor,就有20分啦!

算法3:

简单的树形DP,或者你会nlogn的dij,处理完每个点到其它点的最短路后再加上xor,那么这样就有30分啦!

算法4:

第4、5个点无需xor,那么我们树形DP扫一个节点与其它所有节点的路径长度之和,可以合并信息,最终均摊O(1),50分到手。

算法5:

第6个点xor 1,那么我们树形DP到一个点时记录有多少个0,多少个1,然后每当一条路径到2,那部分就再记录一个值,60分到手。

算法6:

如果你第6个点都过了,却没有满分,笨死啦!

一样的嘛,就是原来的“0”、“1”、大于等于2变成了0~16么~~

 


 

下面是自己的话:

 既然是棵树,又要快速地求每个点的值,那一定是树形DP加上换根的操作啦~

但是异或m要怎么处理呢?可以观察数据规模,发现m最大最大也就15,换成二进制数也就是 1111,所以发现异或m最多只会对数字的后面4位造成影响(异或0甚至无法造成什么影响)

于是愉快地写出DP数组 f[i]sz[i][0~15]

 f表示此时以i为根的子树到i节点的距离之和(减去后缀后的和)

  sz表示此时距离以j为后缀的共有几个

每一次向根节点方向转移时会加上一条边的长度,此时不同后缀距离的后缀会发生相应改变,然后更新父亲相应后缀的sz值。

然后f里统计的距离总和是抹掉所有后缀后的总和,即不考虑后缀的贡献。如有一个距离是 10111(2),抹去长度为2的后缀后就只剩下10100,然后将这个结果加到f数组里,到最后根节点统计最终答案时再考虑每个后缀的贡献,此时的sz数组就派上用场了(具体看代码)

还有一点,就是最后要把答案减去m,因为统计后缀贡献时,多加了自己到自己的距离(本来为0,xor m 后变成了m)。

代码如下

1 #include
2 #include
3 #include
4 #include
5 #include
6 7 #define For(i,a,b) for(register int i=a;i<=b;++i) 8 #define Re register 9 #define Pn putchar('\n') 10 #define inf 0x7f7f7f 11 #define llg long long 12 using namespace std; 13 const int N=1e5+10; 14 int sz[N][17]; 15 int head[N],nxt[N*2],v[N*2],cnt=1; 16 llg w[N*2],z,fn[N],f[N]; 17 int n,m,x,y,ct,tot; 18 19 inline void read(int &v){ 20 v=0; 21 char c=getchar(); 22 while(c<'0'||c>'9')c=getchar(); 23 while(c>='0'&&c<='9')v=v*10+c-'0',c=getchar(); 24 } 25 inline void read(llg &v){ 26 v=0; 27 char c=getchar(); 28 while(c<'0'||c>'9')c=getchar(); 29 while(c>='0'&&c<='9')v=v*10+c-'0',c=getchar(); 30 } 31 void write(llg x){ 32 if(x>9)write(x/10); 33 int xx=x%10; 34 putchar(xx+'0'); 35 } 36 37 void add(int ux,int vx,llg wx){ 38 cnt++; 39 nxt[cnt]=head[ux]; head[ux]=cnt; v[cnt]=vx; w[cnt]=wx; 40 cnt++; 41 nxt[cnt]=head[vx]; head[vx]=cnt; v[cnt]=ux; w[cnt]=wx; 42 } 43 44 void DFS1(int x,int fa){ 45 sz[x][0]=1; 46 for(Re int i=head[x];i;i=nxt[i]){ 47 int vv=v[i]; 48 if(vv==fa)continue; 49 DFS1(vv,x); 50 f[x]+=f[vv]; 51 For(j,0,tot){ 52 int Nsm=j+w[i]; 53 int Nst=Nsm & ct; 54 sz[x][Nst]+=sz[vv][j]; 55 f[x]+=sz[vv][j]*(Nsm-Nst); 56 } 57 } 58 } 59 int Bsz[N][20]; 60 void DFS2(int x,int fa){ //换根 61 fn[x]=f[x]; 62 For(st,0,tot){ 63 fn[x]+=(st^m)*sz[x][st]; 64 } 65 For(st,0,tot)Bsz[x][st]=sz[x][st]; 66 llg Bf=f[x]; 67 68 for(Re int i=head[x];i;i=nxt[i]){ 69 int vv=v[i]; 70 if(vv==fa)continue; 71 72 int Nsm,Nst; 73 74 For(st,0,tot){ 75 Nsm =st+w[i]; 76 Nst=Nsm&ct; 77 sz[x][Nst]-=sz[vv][st]; 78 f[x]-=sz[vv][st]*(Nsm-Nst); 79 } 80 81 f[vv]=f[x]; 82 For(st,0,tot){ 83 Nsm=st+w[i]; 84 Nst=Nsm&ct; 85 sz[vv][Nst]+=sz[x][st]; 86 f[vv]+=sz[x][st]*(Nsm-Nst); 87 } 88 89 DFS2(vv,x); 90 91 f[x]=Bf; 92 For(st,0,tot)sz[x][st]=Bsz[x][st]; 93 } 94 } 95 96 int main(){ 97 // freopen("warehouse.in","r",stdin); 98 // freopen("warehouse.out","w",stdout); 99 read(n); read(m);100 101 if(m==0)ct=0,tot=0;102 if(m==1)ct=1,tot=1;103 if(m==5)ct=7,tot=7;104 if(m==6)ct=7,tot=7;105 if(m>=9)ct=15,tot=15; //简单粗暴的预处理 106 107 For(i,1,n-1){108 read(x); read(y); read(z);109 add(x,y,z);110 }111 DFS1(1,0);112 DFS2(1,0);113 For(i,1,n){114 write(fn[i]-m); Pn;115 }116 return 0;117 }

 

 

 

 

转载于:https://www.cnblogs.com/HLAUV/p/9890073.html

你可能感兴趣的文章
【Web动画】SVG 实现复杂线条动画
查看>>
修改mysql数据库默认存储引擎和默认编码
查看>>
[TJOI2009] 战争游戏
查看>>
eclipse error
查看>>
微信小程序运行机制
查看>>
安卓新发布机制----app bundle
查看>>
3. 设计模式之创建模式
查看>>
python学习笔记-day6-【python如何写excel表】
查看>>
Switch的簡化
查看>>
tensorflow学习笔记一:安装调试
查看>>
(转自ztp800201) Android - 自定义标题栏(在标题栏中增加按钮和文本居中)
查看>>
领扣简单版--两数之和(Two Sum)
查看>>
第10月第25天 java annotation
查看>>
Spark- SparkSQL中 Row.getLong 出现NullPointerException错误的处理方法
查看>>
9.28 作业 6
查看>>
23. Merge k Sorted Lists
查看>>
CentOS7配置JAVA环境变量
查看>>
mysql 批量删除之大坑
查看>>
【Packet Tracer 实验笔记5】
查看>>
利用Opencv在PictureControl中显示照片
查看>>