CSU 1126 DFS前缀和

在一棵树上找影响最小的某个点,某个点的影响是等于其他点到他的距离*其他点的权值 的和

我一开始也找不到什么好的方法,只能想到每个点暴力去判断,但是这样肯定会超时(10^5个点),又有点想用类似前缀和,但是这是在树上,不是很好搞

不过最后还是得用到前缀和,先dfs1把从0号节点出发的整个值算出来,并且沿途记录权值前缀和。之后再用一个dfs2从0号节点开始转移,因为有之前预处理的前缀和以及总和,每次转移只要O(1)复杂度就可以算出来。整个两次dfs都仅仅对每个点搜索了一遍,不会超时

代码不是我写的 用来参考

#include <iostream>
#include <vector>
using namespace std;

int N;
long long cost[1<<17], cows[1<<17], down[1<<17], up[1<<17];
vector<vector<long long> > e, w;

long long dfs1(int cur, int prev) {
  down[cur] = cows[cur];
  long long c = 0;
  for(int i = 0; i < e[cur].size(); i++) {
    if(e[cur][i] == prev) continue;
    c += dfs1(e[cur][i], cur);
    c += down[e[cur][i]]*w[cur][i];
    down[cur] += down[e[cur][i]];
  }
  return c;
}

long long dfs2(int cur, int prev) {
  long long c = cost[cur];
  for(int i = 0; i < e[cur].size(); i++) {
    if(e[cur][i] == prev) continue;
    cost[e[cur][i]] = cost[cur]-down[e[cur][i]]*w[cur][i]+up[e[cur][i]]*w[cur][i];
    c = min(c, dfs2(e[cur][i], cur));
  }
  return c;
}

int main() {
  //FILE* in = fopen("red.in", "r");
  //FILE* out = fopen("red.out", "w");

  scanf("%d", &N);
  e.resize(N); w.resize(N);
  for(int i = 0; i < N; i++) scanf("%lld", &cows[i]);
  for(int i = 0; i < N-1; i++) {
    long long a, b, c;
    scanf("%lld %lld %lld", &a, &b, &c);
    a--; b--;
    e[a].push_back(b); w[a].push_back(c);
    e[b].push_back(a); w[b].push_back(c);
  }

  cost[0] = dfs1(0, -1);
  for(int i = 0; i < N; i++) up[i] = down[0] - down[i];
  printf("%lld\n", dfs2(0, -1));

  //fclose(in);
  //fclose(out);
}

CSU 1126 DFS前缀和

时间: 2024-10-08 20:44:11

CSU 1126 DFS前缀和的相关文章

hdu 5416 CRB and Tree(dfs+前缀和)

题意: 在一棵树上有n个点,n-1条边,每条边都有一个权值. 令f(u,v)等于u到v这条路径上的前缀和. 现在给你Q次询问(Q<=10) 询问f(u,v)=s的路径有多少条. 解析: 由于Q比较小可以直接利用O(n)复杂度的算法来做. 先用sum[u]保存下,从根节点到u的异或和是多少. 用一个hash map来保存,sum[u]出现了多少次. 每次就查询hash map中s ^ sum[u]出现了多少次. 查询的总和除以2就是最终结果. 注意: 如果s=0时,f(u,u)也满足条件,所以还要

Spark学习笔记-hadoop命令

进入 $HADOOP/bin 一.文件操作 文件操作 类似于正常的linux操作前面加上“hdfs dfs -” 前缀也可以写成hadoop而不用hdfs,但终端中显示 Use of this script to execute hdfs command is deprecated.Instead use the hdfs command for it. 1.创建目录:(注意 文件夹需一级一级创建) hdfs dfs -mkdir /user hdfs dfs -mkdir /user/com

[考试反思]0122省选模拟12:延迟

博客咕过了一年我也就忘了我考试状态了2333. T1是弱智题但是没想...写个暴力跑路了(时间不够,主要投在T2/3上了) 然而其实想到了一个乱搞,觉得能得分的概率不大,结果数据奇水完全不对的玩意还有20分,然而我并没有写... 然而T2写的是正解,虽说没有其他人的状压优秀,T了一个细节WA了一个拿了80分,凑合吧. 然后T3时间不多的时候写的,拿个暴力,想到了正解大概怎么写但是没有写,太恶心. 考后改题写了写,一下午就过去了...一晚上也就过去了...弄得跟我颓废了半天一样... 然而是真xx

Trie树 + DFS - CSU 1457 Boggle

Boggle Problem's Link: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1457 Mean: 给定n个串,有m个询问. 每个询问给你一个4*4的字符矩阵,你可以在这个字符矩阵中任意字符出发,向四个方向走(已走过的不可重复走),走出一个字符串. 如果n个串中有对应的串和走出的字符串相同,那么需要求出: 1.不同长度的串给了不同的权值,n个串中出现的串的总权值是多少? 2.从出现的字符串中找一个最长的出来,如果有多个,找一个字典

csu oj 1804: 有向无环图 (dfs回溯)

题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1804 中文题意就不说了. dfs从底到根回溯即可,看代码应该能清楚. 1 //#pragma comment(linker, "/STACK:102400000, 102400000") 2 #include <algorithm> 3 #include <iostream> 4 #include <cstdlib> 5 #include

CSU - 1356 Catch(dfs染色两种写法,和hdu4751比较)

Description A thief is running away! We can consider the city where he locates as an undirected graph in which nodes stand for crosses and edges stand for streets. The crosses are labeled from 0 to N–1. The tricky thief starts his escaping from cross

(ST表+二分+前缀和)CSU 1879 - Hack Protection

题意: 给定一个序列,求异或和与按位与和相同的区间有几个. 异或和:n个数异或起来.按位与和类似. 分析: 这才是神题,基础算法大杂烩. 问大佬这题的时候,人家只说很不难啊.. 只能说自己太菜. 由于询问区间个数,自然要快速知道某一个区间的异或和与按位与和. 异或和很简单,利用他的性质,直接求前缀和即可. 但是按位与没有和加法和异或类似的性质,无法直接求出. 但是利用之前的知识可以将所有结果预处理出来,而且只要nlogn的复杂度. 就是之前搞RMQ的ST表,很适合离线查询. 几乎不用动的把 mi

CSU 1660 K-Cycle(dfs判断无向图中是否存在长度为K的环)

题意:给你一个无向图,判断是否存在长度为K的环. 思路:dfs遍历以每一个点为起点是否存在长度为k的环.dfs(now,last,step)中的now表示当前点,last表示上一个访问的 点,step一个记录路径长度的计数器,s[i]记录从起点到i点的路径长度.如果某点被访问第二次,则说明出现环,判断当前路径长度和它第一次出现是的 长度差是否等于K即可. #include<cstdio> #include<cstring> using namespace std; const in

UVA 12510/CSU 1119 Collecting Coins DFS

前年的省赛题,难点在于这个石头的推移不太好处理 后来还是看了阳神当年的省赛总结,发现这个石头这里,因为就四五个子,就暴力dfs处理即可.先把石头当做普通障碍,进行一遍全图的dfs或者bfs,找到可以找的点,然后dfs每次探索新区域的新点即可,想通了这里很好做了 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; c