练习赛
2015-09-10 14:00
253 查看
Problem I
Time Limit : 3000/5000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)Total Submission(s) : 36 Accepted Submission(s) : 8
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
一颗N个点的树,求每个点到其他所有点的路径长度异或K的总和。即ANSi=sum(distance(i,j) xor K){1<=j<=N, j!=i}
Input
第一行一个整数t,测试数据组数每组数据第一行两个整数N,K 如题述。(N<=10^5,K<16)
然后N-1 行每行三个整数a,b,c 表示a 到b 有一条长为c 的边。
Output
对于每组数据输出N行。第i 行为ANSi。
Sample Input
1 4 0 1 4 3 1 3 2 1 2 1
Sample Output
6 8 10 12
首先我们假设没有异或,那么先算出其他所有点到1的距离,然后已知所有点到他的父亲的距离,可以推知所有点到这个点的距离
比如,sum[fa]表示所有点到这个点父亲的距离的和,sum1[v]表示他的子孙到他的距离和,设他和他的父亲之间的距离为x,他的子孙
数目为sz[v],]那么所有点到他的距离和便为sum[v]+(sum[fa]-sum1[v])+(n-sz[v])*x
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+100; typedef long long ll; typedef pair<ll,ll>pi; vector<pi>G[maxn]; ll sz[maxn]; ll dp[maxn][17]; ll sum1[maxn],sum[maxn]; ll rep[maxn]; int w,n; void dfs1(int u,int p){ sz[u]=1; sum[u]=0; for(int i=1;i<16;i++) dp[u][i]=0; dp[u][0]=1; for(int i=0;i<G[u].size();i++){ int v=G[u][i].first; int k=G[u][i].second; if(v==p) continue; dfs1(v,u); sum1[v]=0; int x=k/16,y=k%16; sz[u]+=sz[v]; sum[u]+=sum[v]+sz[v]*16*x; //sum[]一定为16的倍数 sum1[v]+=sum[v]+sz[v]*16*x; //sum[v]-sum1[v]即为不是他的子孙到他的距离 for(int j=0;j<16;j++){ dp[u][(j+y)%16]+=dp[v][j]; if(j+y>=16){ sum[u]+=dp[v][j]*16; sum1[v]+=dp[v][j]*16; } } } } void dfs2(int u,int p){ rep[u]=sum[u]; //printf("u is %d sum[u] is %I64d\n",u,sum[u]); for(int i=0;i<16;i++){ //if(u==1){ //printf("%d\n",dp[u][i]); //} rep[u]+=dp[u][i]*(i^w); } for(int i=0;i<G[u].size();i++){ int v=G[u][i].first; int k=G[u][i].second; if(v==p) continue; int x=k/16,y=k%16; sum[v]+=(sum[u]-sum1[v]); sum[v]+=(n-sz[v])*16*x; vector<int>V; V.assign(17,0); for(int j=0;j<16;j++){ V[(j+y)%16]+=dp[u][j]-dp[v][(j-y+16)%16]; if(j+y>=16){ sum[v]+=(dp[u][j]-dp[v][(j-y+16)%16])*16; } } for(int j=0;j<16;j++) dp[v][j]+=V[j]; dfs2(v,u); } } void init(int n){ for(int i=1;i<=n;i++) G[i].clear(); } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&w); init(n); int u,v,k; for(int i=1;i<n;i++){ scanf("%d%d%d",&u,&v,&k); G[u].push_back(pi(v,k)); G[v].push_back(pi(u,k)); } dfs1(1,0); dfs2(1,0); for(int i=1;i<=n;i++) printf("%I64d\n",rep[i]-w); } return 0; }
相关文章推荐
- SES机箱管理知识回顾(一) 之SES标准介绍
- 简析Serializable 和 Parcelable 区别
- 《TCP/IP详细说明》读书笔记(17章)-TCP传输控制协定
- mciSendString用法
- 面试算法题
- 用户想要的功能就该给吗?
- Build Settings中的变量@rpath,@loader_path,@executable_path
- Android drawable selector foucus,pressed,selected的区别
- freemarker 空白处理
- VirtuablBox 出错: VERR_SUPLIB_OWNER_NOT_ROOT 解决方法
- SQL SERVER 2000数据库置疑处理
- C#打印条码与ZPL
- 计算百分比-比例函数ratio_to_report
- android View 绘制机制
- [Android] Android开发优化之——使用软引用和弱引用
- 诗词—《吾念谁悲》
- 诗词—《吾念谁悲》
- windows下bat文件打开目录
- Android SDK manager镜像服务器
- Spring、MyBatis、Struts框架整合的jar