bzoj 1912 tree_dp】的更多相关文章

这道题我们加一条路可以减少的代价为这条路两端点到lca的路径的长度,相当于一条链,那么如果加了两条链的话,这两条链重复的部分还是要走两遍,反而对答案没有了贡献(其实这个可以由任意两条链都可以看成两条不重叠的链来证明),那么这道题k=2的时候就转化为了求出树上两条链,使得两条链不重叠的长度最大,那么答案就是(n-1)<<1-SumLen+2.当k=1的时候我们直接求出来树的最长链然后减去就好了,这个在此不再赘述. 对于树上两链不重复部分最大我们是可以tree_dp的,设w[i][0..4]来表示…
题目: https://www.lydsy.com/JudgeOnline/problem.php?id=1912 题解: 首先,显然当不加边的时候,遍历一棵树每条边都要经过两次.那么现在考虑k==1的情况,考虑加入的这一条边有什么作用. 显然,如图4边的作用就是使得原来的1-2-3-3-2-1路线变为了4-3-2-1或1-2-3-4,那么作用就是以多走一步的代价使得这条新边两端的两个结点的遍历路径长度减半. 因此,想要使路径最短,就要使这条新边两端的两个结点之间的距离更长,显然,当两端的结点在…
Link:https://www.lydsy.com/JudgeOnline/problem.php?id=1912 Algorithm: K=0:res=(n-1)*2   每条边恰好走2遍 K=1:res=res-树上最长链+1 由于每形成环,环上的边对答案的贡献都会-1,因此只要将树上最长链连成环即可 K=2:res=res-树上当前最长链+1 将原树上直径的边的边权赋为-1,表示如果原直径边同时出现在第2个环时对答案贡献增加1(变为2) 证明:第二次求最长链相当于对第一次的“反悔”操作,…
1912: [Apio2010]patrol 巡逻 Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n). Output 输出一个整数,表示新建了K 条道路后能达到的最小巡逻距离. Sample Input 8 1 1 2 3 1 3 4 5 3 7 5 8 5 5 6 Sample Output 11 HINT 10%的数据中,n ≤ 1000, K = 1: 30%的数据中,K…
重赋边权. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxv 100500 #define maxe 200500 #define inf 2000000000 using namespace std; ,fath_w[maxv],dis[maxv],pos,ret=,root=,tot=,fath[maxv]; int dp1[max…
Description Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n). Output 输出一个整数,表示新建了K 条道路后能达到的最小巡逻距离. Sample Input 8 1 1 2 3 1 3 4 5 3 7 5 8 5 5 6 Sample Output 11 HINT 10%的数据中,n ≤ 1000, K = 1: 30%的数据中,K = 1: 80%的数据中,…
题目链接 如果k==1, 显然就是直径. k==2的时候, 把直径的边权变为-1, 然后在求一次直径. 变为-1是因为如果在走一次这条边, 答案会增加1. 学到了新的求直径的方法... #include <bits/stdc++.h> using namespace std; #define pb(x) push_back(x) #define ll long long #define mk(x, y) make_pair(x, y) #define lson l, m, rt<<…
树的直径 这题如果k=1很简单,就是在树的最长链上加个环,这样就最大化的减少重复的路程 但是k=2的时候需要考虑两个环的重叠部分,如果没有重叠部分,则和k=1的情况是一样的,但是假如有重叠部分,我们可以先把树直径找出来(最长链),然后把路径上的边权全部取反(1变-1),再找一次树的直径,如果第二次找的直径包含了取反的部分(即为重叠部分),这个重叠部分显然需要走两次. 可以推得答案为:2(n-1)-(L1-1)-(L2-1) 如果没有重叠部分,那么显然正确:假如有重叠部分,我们先减去了(L1-1)…
本来抄了篇题解,后来觉得题解都太不友好(我太菜了),一气之下自己打...一打打到第二天QAQ 首先什么边也不加时,总路程就是2*(n-1) 考虑k=1的时候,答案显然是2*(n-1)-直径+1=2*n-直径-1,如果能加一条边的话,因为希望减少的尽可能多,那么只需要把直径的首尾接起来,就不需要来回走,加一就是加了这一条新加入的边. 而k=2的时候,首先还是往最长链上面思考.然而做k=1的时候已经用掉了一段,我们需要k=2的和k=1的不重叠. 于是乎,我们跑完直径后之后把直径上的边权全部修改为-1…
我是智障系列.用了及其麻烦的方法= =其实树形sp就能解决 设直径长度+1为len(环长) 首先k=1,直接连直径两端就好,答案是2*n-len 然后对于k=2,正常人的做法是树形dp:先求直径,然后把树的直径上的所有边权标为-1,再求一次直径设新直径+1为len2,答案是2*(n−1)−len−len2. 然后zz的做法是分两种情况: len=n,直接输出n+1(因为要加个自环) 否则,答案可能从两种情况产生: 新选出的链两端在都原直径环某一个节点下面,这样的情况可以直接求这个节点子树的直径+…