BZOJ 1912 巡逻】的更多相关文章

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%的数据中,…
重赋边权. #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…
树的直径 这题如果k=1很简单,就是在树的最长链上加个环,这样就最大化的减少重复的路程 但是k=2的时候需要考虑两个环的重叠部分,如果没有重叠部分,则和k=1的情况是一样的,但是假如有重叠部分,我们可以先把树直径找出来(最长链),然后把路径上的边权全部取反(1变-1),再找一次树的直径,如果第二次找的直径包含了取反的部分(即为重叠部分),这个重叠部分显然需要走两次. 可以推得答案为:2(n-1)-(L1-1)-(L2-1) 如果没有重叠部分,那么显然正确:假如有重叠部分,我们先减去了(L1-1)…
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…
题目: 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) 证明:第二次求最长链相当于对第一次的“反悔”操作,…
题目链接 如果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<<…
本来抄了篇题解,后来觉得题解都太不友好(我太菜了),一气之下自己打...一打打到第二天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(因为要加个自环) 否则,答案可能从两种情况产生: 新选出的链两端在都原直径环某一个节点下面,这样的情况可以直接求这个节点子树的直径+…
呵呵呵呵呵呵,自己画图,大概半个小时,觉的连上边会成环(是不是该交仙人掌了??)然后求环不重合部分最大就好了, 结果写了一坨DP,最后写不下去了,再次扒了题解. 发现我真的是个sb. k==1,直接是直径 k==2,搞出直径然后把直径删掉(把权值赋为-1,再找直径)(有点像我一开始想的每次找个最长链去贪心,然而,,总觉得,这种题贪心这么可能对) /*#include <bits/stdc++.h> #define LL long long #define lowbit(x) x&(-x…