제출 #164573

#제출 시각아이디문제언어결과실행 시간메모리
164573faremyFactories (JOI14_factories)C++14
100 / 100
6150 ms189680 KiB
#include "factories.h"

#include <vector>


struct Edge
{
	Edge(int e, long long w) : end(e), weight(w) {}
	int end;
	long long weight;
};

const int MAXN = 5e5;
const int LOGN = 20;
const long long INFTY = 1e18;

std::vector<Edge> tree[MAXN];
bool seen[MAXN];
int size[MAXN];

int centrParent[MAXN], centrDepth[MAXN];
long long centrDist[MAXN][LOGN];

long long minActive[MAXN];


void calcsize(int node)
{
	seen[node] = true;
	size[node] = 1;

	for (Edge& edge : tree[node])
		if (!seen[edge.end])
		{
			calcsize(edge.end);
			size[node] += size[edge.end];
		}
	
	seen[node] = false;
}

int findcentr(int node, int treesize)
{
	if (seen[node])
		return 0;
	seen[node] = true;

	int maxSubSize = treesize - size[node];
	for (Edge &edge : tree[node])
	{
		int ans = findcentr(edge.end, treesize);
		if (ans < 0)
		{
			seen[node] = false;
			return ans;
		}

		maxSubSize = std::max(maxSubSize, ans);
	}

	seen[node] = false;
	if (maxSubSize <= treesize / 2)
		return (-1 - node);
	return size[node];
}

void calcdist(int node, long long dist)
{
	if (seen[node])
		return;
	seen[node] = true;

	centrDist[node][centrDepth[node]] = dist;
	centrDepth[node]++;

	for (Edge &edge : tree[node])
		calcdist(edge.end, dist + edge.weight);
	seen[node] = false;
}

void buildcentr(int node, int parent)
{
	calcsize(node);
	int centroid = (-1 - findcentr(node, size[node]));

	centrParent[centroid] = parent;
	seen[centroid] = true;

	for (Edge &edge : tree[centroid])
		if (!seen[edge.end])
			buildcentr(edge.end, centroid);

	seen[centroid] = false;
	calcdist(centroid, 0);
	minActive[centroid] = INFTY;
}

void Init(int N, int A[], int B[], int D[])
{
	for (int iEdge = 0; iEdge < N - 1; iEdge++)
	{
		tree[A[iEdge]].emplace_back(B[iEdge], D[iEdge]);
		tree[B[iEdge]].emplace_back(A[iEdge], D[iEdge]);
	}

	buildcentr(0, -1);
}

long long Query(int S, int X[], int T, int Y[])
{
	for (int iNode = 0; iNode < S; iNode++)
	{
		int ancester = X[iNode];
		for (int iAnc = 0; iAnc < centrDepth[X[iNode]]; iAnc++)
		{
			minActive[ancester] = std::min(minActive[ancester], centrDist[X[iNode]][iAnc]);
			ancester = centrParent[ancester];
		}
	}

	long long minDist = INFTY;
	for (int iNode = 0; iNode < T; iNode++)
	{
		int ancester = Y[iNode];
		for (int iAnc = 0; iAnc < centrDepth[Y[iNode]]; iAnc++)
		{
			minDist = std::min(minDist, minActive[ancester] + centrDist[Y[iNode]][iAnc]);
			ancester = centrParent[ancester];
		}
	}

	for (int iNode = 0; iNode < S; iNode++)
		for (int ancester = X[iNode]; ancester != -1; ancester = centrParent[ancester])
			minActive[ancester] = INFTY;

	return minDist;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...