A 求和
时间限制: 1 Sec 空间限制: 256 MB

输入输出文件名:A.in,A.out

题目描述
给出一棵以1为根的有n个节点的树,树上每条边都有其边权。

求所有点对之间的路径上的边权和的总和。

输入格式:
第一行为n

接下来n-1行,每行三个整数,分别表示一条边的两端点编号和边权。(编号为1..n)

输出格式:
输出一个数字表示总和

输入样例
4

1 2 10

2 3 10

1 4 20

输出样例
130

样例解释
1->2:10 , 1->3:20 , 1->4:20 , 2->3:10 , 2->4:30 , 3->4:40 , 总和为130。

数据范围
对于30%的数据,1<=n<=300

对于80%的数据,1<=n<=3000

对于100%的数据,1<=n<=100000,边权为<=100的正整数。


这题的做法是考虑每条边对答案的贡献(套路题QAQ)

即考虑有多少条路径经过这条边

易知即边左边的点的数目*另一边的点的数目

我们可以先从根节点dfs一遍求出每个节点的子树的大小

即一边的点的数目

这样就可以得到贡献为 cost * size[e[k].to]*(n-size[e[k].to])

#include<cstdio>
#include<cstring>
const int N=100005;
struct node
{  int to,next,c;
}e[N*2];
int first[N],visit[N],size[N];
int cnt=0;
int n;
void insert(int u,int v,int c)
{  e[++cnt].to=v;e[cnt].next=first[u];first[u]=cnt;e[cnt].c=c;  e[++cnt].to=u;e[cnt].next=first[v];first[v]=cnt;e[cnt].c=c;
}
long long ans=0;long long sum=0;
void dfs(int x)
{     visit[x]=1;size[x]=1;  for(int k=first[x];k;k=e[k].next)  if(!visit[e[k].to])  {  dfs(e[k].to);  size[x]+=size[e[k].to];  }
}
void dfs2(int x)
{  visit[x]=1;  for(int k=first[x];k;k=e[k].next)  {  if(!visit[e[k].to])  {  ans+=e[k].c*size[e[k].to]*(n-size[e[k].to]);  dfs2(e[k].to);  }     }
}
int main()
{  scanf("%d",&n);  int u,v,c;  for(int i=1;i<n;i++)   {  scanf("%d %d %d",&u,&v,&c);  insert(u,v,c);  }  dfs(1);  memset(visit,0,sizeof(visit));  dfs2(1);  printf("%lld\n",ans);  return 0;
}

Xor路

(xor.pas/c/cpp) 128MB 1s

给定一棵有N个点和N-1条边的树,请你求出树中的最长路径,以及总共有多少条最长路径。

这里路径长度是用xor定义的,即若经过的边的权值为a1, a2, a3,...,an,则这条路径的总权值为 a1 xor a2 xor a3 ... xor an。

输入格式

第1行为一个正整数 N,为点的个数。

第2行至第N行,每行包含三个正整数x,y,z,表示x和y之间有一条权值为z的边。

输出格式

仅一行,包含两个数字,为最长路径的长度和条数。

样例输入

4

1 2 3

2 4 1

1 3 4

样例输出

7 1

样例解释

2-1-3 这条路径,长度为3 xor 4=7。

数据范围

全部数据满足 0<=z<=1e9

(请注意栈空间溢出)

由xor的性质可得

两个点的路径即为根节点到一个点的路径^根节点到另一个点的路径

然后又由xor的性质可得

高位上两个值的二进制表示不同

异或的结果就为1(这样是最优的)

所以想到建一颗trie树

维护对一个值的最优异或结果

并统计方案数

#include<cstdio>
#include<cstring>
const int N=200005;
struct node
{  int next,to,c;
}e[N*2];
int qu[N+100],dis[N];int cnt=0;int first[N],visit[N];
int l[N*31][2];
int h[N*31];
void insert(int u,int v,int c)
{  e[++cnt].to=v;e[cnt].next=first[u];e[cnt].c=c;first[u]=cnt;  e[++cnt].to=u;e[cnt].next=first[v];e[cnt].c=c;first[v]=cnt;
}
void bfs()
{  int head=1,tail=2;  qu[1]=1;  while(head<=tail)  {  int rr=qu[head++];visit[rr]=1;  for(int k=first[rr];k;k=e[k].next)  if(!visit[e[k].to])  visit[e[k].to]=1,qu[tail++]=e[k].to,dis[e[k].to]=dis[rr]^e[k].c;  }
}
int k=0;
int tot=0;
void insert(int x)
{  int ro=0;  for(int i=30;i>=0;i--)  {  int cnt=(x&(1<<i))>>i;  if(!l[ro][cnt]) l[ro][cnt]=++tot;  ro=l[ro][cnt];  }  h[ro]++;
}
int find(int x)
{  int ro=0;  for(int i=30;i>=0;i--)  {  int cnt=(x&(1<<i))>>i;  if(l[ro][!cnt]) ro=l[ro][!cnt],k+=(1<<i);  else ro=l[ro][cnt];  }  return h[ro];
}
int main()
{  freopen("xor.in","r",stdin);  freopen("xor.out","w",stdout);  int n;  scanf("%d",&n);  int u,v,c;  for(int i=1;i<n;i++)  scanf("%d %d %d",&u,&v,&c),insert(u,v,c);  bfs();  for(int i=1;i<=n;i++)    insert(dis[i]);  long long int max=0,sum=0;  for(int i=1;i<=n;i++)  {  k=0;int p=find(dis[i]);  if(k>max)        max=k,sum=p;  else if(k==max) sum+=p;  }  printf("%lld %lld\n",max,sum>>1);  fclose(stdin);  fclose(stdout);  return 0;
}  

T3

时间限制: 1 Sec 空间限制: 256 MB

输入输出文件名:B.in,B.out

题目描述
给出一棵以1为根的有n个节点的树,树上每条边都有其边权。

四条琉璃想选择一个点作为起点,他希望这个起点到其他所有点距离和是最小的。

输入格式:
第一行为n

接下来n-1行,每行三个整数,分别表示一条边的两端点编号和边权。(编号为1..n)

输出格式:
一个数,表示那个最小的距离和。

输入样例
5

1 2 10

2 3 10

1 4 20

2 5 10

输出样例
60

样例解释
选2作为起点。2->1:10,2->3:10,2->4:30,2->5:10,总和为60

数据范围
对于40%的数据,1<=n,m<=2333

对于100%的数据,1<=n,m<=300 000,边权为<=100的正整数

这道题很多种方法可以做

方法一:

发现可以O(1)转移

先求出一个节点的答案

然后从一个点转移到另一个点

就+e[k].c * (n-size[e[k].to]) - e[k].c * size[e[k].to]

其实就是求的树的重心

方法二:s

双向树形dp

第一次dfs从儿子上传信息到父亲

即维护一个点到它的子树内每个点的距离之和(big数组)

第二次dfs从父亲下传信息到儿子

即维护到子树外的点的距离之和(f数组)(父亲和兄弟)

转移方程看代码吧

#include<cstdio>
#include<cstring>
const int N=300050;
struct node
{  int next,to,c;
}e[N*2];
int first[N];
int cnt=0;
long long int f[N];
int  n;
void insert(int u,int v,int c)
{  e[++cnt]=(node){first[u],v,c};first[u]=cnt;  e[++cnt]=(node){first[v],u,c};first[v]=cnt;
}
long long int big[N];
int size[N],visit[N];
void dfs1(int x)
{  visit[x]=1;size[x]=1;  for(int k=first[x];k;k=e[k].next)  if(!visit[e[k].to])  {  dfs1(e[k].to);  size[x]+=size[e[k].to];  big[x]+=big[e[k].to]+(long long )e[k].c*size[e[k].to];  }
}
void dfs2(int x)
{  visit[x]=1;  for(int k=first[x];k;k=e[k].next)  if(!visit[e[k].to])  {  f[e[k].to]=f[x]+(big[x]-big[e[k].to]-(long long )size[e[k].to]*e[k].c)+(n-size[e[k].to])*(long long )e[k].c;  dfs2(e[k].to);  }
}
int main()
{  freopen("B.in","r",stdin);  freopen("B.out","w",stdout);  scanf("%d",&n);  int u,v,c;  for(int i=1;i<n;i++)  {  scanf("%d %d %d",&u,&v,&c);  insert(u,v,c);  }  dfs1(1);  memset(visit,0,sizeof(visit));  dfs2(1);  long long min=1e17;  for(int i=1;i<=n;i++)  min=min<big[i]+f[i]?min:big[i]+f[i];  printf("%lld\n",min);  return 0;
}  

转载于:https://www.cnblogs.com/Roni-i/p/9535595.html

几道查询树上点之间的路径的题目相关推荐

  1. 运行shell脚本时怎么知道jdk路径_Linux中如何查询运行文件的全路径的方法

    在linux中,有些地方需要使用绝对路径,对于一些命令,如java.mysql等,需要使用到运行文件所在的路径,给大家介绍一个命令,来查询这个路径. which 可以通过which查询运行文件的所在路 ...

  2. 两点之间的连线java_java计算图两点之间的路径实例代码

    java计算图两点之间的路径总结 本文实例为大家分享了java计算图两点之间的所有路径的具体代码,供大家参考,具体内容如下 1.给定图如下: 2.求0到3之间可达的所有路径 这里问题就是关于搜索遍历的 ...

  3. 数据结构--二叉树--路径 假设二叉树采用二叉链表方式存储, root指向根结点,node 指向二叉树中的一个结点, 编写函数 path,计算root到 node 之间的路径,(该路径包括root结

    假设二叉树采用二叉链表方式存储, root指向根结点,node 指向二叉树中的一个结点, 编写函数 path,计算root到 node 之间的路径,(该路径包括root结点和 node 结点).pat ...

  4. linux中如何运行html文件路径问题,Linux中如何查询运行文件的全路径的方法

    在linux中,有些地方需要使用绝对路径,对于一些命令,如java.mysql等,需要使用到运行文件所在的路径,给大家介绍一个命令,来查询这个路径. which 可以通过which查询运行文件的所在路 ...

  5. C++音频单声道、双声道之间的转换

    本篇文件介绍 音频PCM数据的单声道.双声道之间的转换 下面介绍函数参数: 一.StereoToMono函数. 双声道转单声道 参数1:资源buffer(双声道数据) 参数2:资源buffer大小(双 ...

  6. fastapi 查询参数和字符串校验 / 路径参数和数值校验

    文章目录 1. 约束限制 2. 必须参数 3. 查询参数列表 / 多个值 4. 声明更多元数据 5. 别名参数 6. 弃用参数 7. Path 路径参数 8. 按需对参数排序 learn from h ...

  7. 《MySQL——38道查询练习(无连接查询)》

    目录 一.准备数据 1.创建数据库 2.创建学生表 3.创建教师表 4.创建课程表 5.创建成绩表 6.添加数据 二.查询练习 1.查询 student 表的所有行 2.查询 student 表中的 ...

  8. mysql忽略中英文括号_MySQL查询删除方括号之间的文本?

    让我们首先创建一个表-create table DemoTable -> ( -> Name text -> ); 使用插入命令在表中插入一些记录-insert into DemoT ...

  9. mysql查询 多门课程的平均成绩_MySQL 45道查询习题详解

    1.首先进行建表: 按 Ctrl+C 复制代码 #建学生信息表studentcreate table student ( sno varchar(20) not null primary key, s ...

最新文章

  1. 【好程序员笔记分享】——下拉刷新和上拉加载更多
  2. Hbase 预写日志WAL处理源码分析之 LogCleaner
  3. 锐动SDK针对游戏直播提出的解决方案
  4. Ubuntu20.04下面运行applet与freemind部署到web上(调研+找到替换方案)
  5. SpringBoot在项目中基本配置设置
  6. 谷歌Chrome:将逐步阻止浏览器不安全下载内容
  7. python中的索引从几开始计数_计算机为什么要从 0 开始计数?
  8. SPOJ HIGH Highways
  9. Python list 初始化技巧
  10. Linux 桌面版为什么打不过 Window?Linus 现身说法!
  11. 2022 年移动应用开发终极指南
  12. wox wpm 安装 有道插件
  13. mysql安装步骤图解5.0_MySQL5.0安装图解
  14. 五一济南酒店数据出炉,做一个酒店管理APP多少钱?
  15. 磊科NBR100企业有线路由器IP和Mac地址绑定教程
  16. 阿里P7晒出1月工资单:狠补了这个,真香...
  17. html首页随机飘浮图片,jQuery 全屏随机漂浮图片广告
  18. Excise_day02
  19. GCC 中的 aligned 和 packed 属性(关于地址对齐)
  20. [抖音电商] 抖音电商新学员必看基础课,抖音新手必看运营教程(价值3980)

热门文章

  1. bzoj 3930: [CQOI2015]选数
  2. 《DSP using MATLAB》示例Example 8.10
  3. 链表——【线性表(二)】
  4. 《幸福就在你身边》第一课、你有追求美好生活的权利【哈佛大学幸福课精华】...
  5. SQL基础实例(学生课程系统)
  6. 如何使用JMeter 对Dubbo接口进行测试
  7. raster | R语言中的空间栅格对象及其基本处理方法(Ⅲ):切片/掩膜、图层叠加...
  8. Python 集合定义及运算
  9. 如何评价,为何程序员被骂立马就辞职呢?
  10. 程序员面试时自称字节跳动工作两年,被发现学历造假,结果蒙了