首页 > 其他分享 >洛谷 P6419 [COCI2014-2015#1] Kamp

洛谷 P6419 [COCI2014-2015#1] Kamp

时间:2024-09-06 20:02:36浏览次数:8  
标签:int text ll COCI2014 fa Kamp 2015 define Dis

洛谷 P6419 [COCI2014-2015#1] Kamp

题意

一颗树 \(n\) 个点,\(n-1\) 条边,经过每条边都要花费一定的时间,任意两个点都是联通的。

有 \(K\) 个人(分布在 \(K\) 个不同的点)要集中到一个点举行聚会。

聚会结束后需要一辆车从举行聚会的这点出发,把这 \(K\) 个人分别送回去。

请你回答,对于 \(i=1 \sim n\) ,如果在第 \(i\) 个点举行聚会,司机最少需要多少时间把 \(K\) 个人都送回家。

思路

黑点表示住了人。

若送完最后一个人后再回到起点,答案即为所有黑点到起点的路径并集的边权和。

为了让答案最优,显然删掉最长的那条边。

答案可以表示为:\(2\times \text{sum}-\text{maxdis}\)。

其中 \(\text{sum}\) 可以用换根 DP 简单求出(第一次 DFS 求出根的 \(\text{sum}\),第二次 DFS 分类讨论增删边权转移至儿子节点)。

重点问题在 \(\text{maxdis}\) 上。

我们考虑原树的一棵子树,满足包含所有黑点,并且所有叶子节点都是黑点。

求出这棵树的直径,\(\text{maxdis}\) 只可能是该点与直径两端点的距离,可以用反证法证明。

代码

#include <bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
#define ll long long
using namespace std;
const int N = 5e5 + 5;
vector <pii> E[N];
int n, k, siz[N];
bool a[N];
int fa[N][21], de[N];
ll Dis[N], dp[N], dis[N];
void dfs1(int x) {
	for (int i = 1; i <= 20; i ++)
		fa[x][i] = fa[fa[x][i - 1]][i - 1];
	siz[x] += a[x];
	for (auto e : E[x]) {
		ll y = e.fi, z = e.se;
		if (y == fa[x][0]) continue;
		fa[y][0] = x, de[y] = de[x] + 1;
		Dis[y] = Dis[x] + z; 
		dfs1(y);
		siz[x] += siz[y]; // 子树内黑点个数
		dp[x] += dp[y]; 
		if (siz[y]) dp[x] += z; // 子树内有,增
	}
}
void dfs2(int x) {
	for (auto e : E[x]) {
		ll y = e.fi, z = e.se;
		if (y == fa[x][0]) continue;
		if (siz[y] && (k - siz[y])) dp[y] = dp[x]; // 子树内外都有,不增不减
		else if (!siz[y] && (k - siz[y])) dp[y] = dp[x] + z; // 子树内没有,增
		else if (siz[y] && !(k - siz[y])) dp[y] = dp[x] - z; // 子树外没有,减
		dfs2(y); 
	}
}
int LCA(int x, int y) {
	if (de[x] < de[y]) swap(x, y);
	for (int i = 20; i >= 0; i --)
		if (de[fa[x][i]] >= de[y]) x = fa[x][i];
	if (x == y) return x;
	for (int i = 20; i >= 0; i --)
		if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
	return fa[x][0];
}
ll getDis(int x, int y) {return Dis[x] + Dis[y] - Dis[LCA(x, y)] * 2ll;}
void dfs3(int x, int FA) {
	for (auto e : E[x]) {
		ll y = e.fi, z = e.se;
		if (y == FA) continue;
		dis[y] = dis[x] + z;
		dfs3(y, x);
	}
}
int main() {
	cin >> n >> k;
	for (int i = 1, u, v, w; i < n; i ++) {
		cin >> u >> v >> w;
		E[u].push_back({v, w});
		E[v].push_back({u, w});
	}
	for (int i = 1, x; i <= k; i ++)
		cin >> x, a[x] = 1;
	dfs1(1); dfs2(1);
	int P1 = 0, P2 = 0;
	dfs3(1, 0); 
	for (int i = 1; i <= n; i ++) // 直径 
		if (a[i] && dis[P1] < dis[i]) P1 = i; 
	memset(dis, 0, sizeof(dis));
	dfs3(P1, 0);
	for (int i = 1; i <= n; i ++)
		if (a[i] && dis[P2] < dis[i]) P2 = i;
	for (int i = 1; i <= n; i ++) // maxdis
		dis[i] = max(getDis(i, P1), getDis(i, P2));
	for (int i = 1; i <= n; i ++) 
		cout << dp[i] * 2ll - dis[i] << "\n";
	return 0;
}
/*
7 2
1 2 4
1 3 1
2 5 1
2 4 2
4 7 3
4 6 2
3
7
*/

标签:int,text,ll,COCI2014,fa,Kamp,2015,define,Dis
From: https://www.cnblogs.com/maniubi/p/18400912

相关文章

  • 修复Microsoft Visual C++ 2015中msvcp140_ATOMIC_WAIT.dll缺失的5大策略
    在电脑使用过程中,我们经常会遇到一些错误提示,其中之一就是“msvcp140_ATOMIC_WAIT.dll丢失”。这个错误提示通常出现在运行某些程序或游戏时,给使用者带来了很大的困扰。那么,如何解决这个问题呢?一,原因分析msvcp140_ATOMIC_WAIT.dll是MicrosoftVisualC++2015运行时库的一部......
  • 信息学奥赛初赛天天练-81-NOIP2015普及组-完善程序-二分答案、二分查找、中位数、二分
    1完善程序(单选题,每小题3分,共30分)中位数median给定n(n为奇数且小于1000)个整数,整数的范围在0∼m(0<m<2^31)之间,请使用二分法求这n个整数的中位数。所谓中位数,是指将这n个数排序之后,排在正中间的数。(第五空2分,其余3分)01#include<iostream>02usingnamespace......
  • 信息学奥赛初赛天天练-80-NOIP2015普及组-基础题5-错位排列、二叉树、完全二叉树、叶
    NOIP2015普及组基础题521重新排列1234使得每一个数字都不在原来的位置上,一共有()种排法22一棵结点数为2015的二叉树最多有()个叶子结点2相关知识点1)错位排列考虑一个有n个元素的排列,若一个排列中所有的元素都不在自己原来的位置上,那么这样的排列就......
  • P3320 [SDOI2015] 寻宝游戏 与 P10930 异象石 与 CF176E Archaeology
    思路:考虑按照dfn序将关键点的集合排序后为\(a_0,a_1,\cdots,a_k\),则答案为:\[\frac{\sum\limits_{i=0}^k\operatorname{dis}(a_i,a_{(i+1)\bmodk})}{2}\]简单证明一下:需要找出包含一些关键点的最小联通导出子图。则随便以一个关键点为根,对于子树内没有关键点的子树直接......
  • 洛谷 P2680 [NOIP2015 提高组] 运输计划
    洛谷P2680[NOIP2015提高组]运输计划题意给出一棵树和\(m\)条路径,可以选择一条边,把边权改为\(0\),求\(m\)条路经长度最大值的最小值。思路看到最大值最小,可以想到二分答案,答案具有单调性。考虑如何判定答案\(x\)是否可行。统计所有长度大于\(x\)的路径,统计它们共......
  • 信息学奥赛初赛天天练-78-NOIP2015普及组-基础题3-中断、计算机病毒、文件传输协议FTP
    NOIP2015普及组基础题38所谓的“中断”是指()A操作系统随意停止一个程序的运行B当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的过程C因停机而停止一个程序的运行D电脑死机9计算机病毒是()A通过计算机传播的危害人体健康的一种......
  • P1955 [NOI2015] 程序自动分析
    算法1(离散化+并查集)没想到的点:由于数据范围很大1e9,因此需要采用离散化,从而降低时间复杂度主要思想1.约束条件有相等/不相等,不难发现,相等的约束条件是属于一个集合的--因此需要用到并查集思想我们按照e的大小进行排序,从而完成先处理e=1的所有情况3.并查集:初始化:一......
  • 信息学奥赛初赛天天练-77-NOIP2015普及组-基础题2-二进制、连通图、最小生成树、链表
    NOIP2015普及组基础题24在计算机内部用来传送、存贮、加工处理的数据或指令都是以()形式进行的A二进制码B八进制码C十进制码D智能拼音码5下列说法正确的是()ACPU的主要任务是执行数据运算和程序控制B存储器具有记忆能力,其中信息任何时候都不会......
  • 信息学奥赛初赛天天练-76-NOIP2015普及组-基础题1-计算机存储、硬件系统、操作系统、
    NOIP2016普及组基础题111MB等于()A10000字节B1024字节C1000×1000字节D1024×1024字节2在PC机中,PENTIUM(奔腾)、酷睿、赛扬等是指()A生产厂家名称B硬盘的型号CCPU的型号D显示器的型号3操作系统的作用是()A把源程序译成目......
  • 题解:P3266 [JLOI2015] 骗我呢
    题意有一个\(n\timesm\)的数组\(x_{i,j}(1\lei\len,1\lej\lem)\),满足:\(x_{i,j}\in[0,m]\)\(\foralli\in[1,n],\forallj\in[1,m),x_{i,j}<x_{i,j+1}\)\(\foralli\in(1,n],\forallj\in[1,m),x_{i,j}<x_{i-1,j+1}\)......