记录编号 211191 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOIP 2015]运输计划 最终得分 100
用户昵称 Gravatarzhengtn03 是否通过 通过
代码语言 C++ 运行时间 1.368 s
提交时间 2015-11-30 17:53:38 内存使用 37.63 MiB
显示代码纯文本
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<sstream>
#include<iomanip>
#include<stdlib.h>
using namespace std;

#define maxn 300010
char *in = (char*)malloc(10000000);
inline int scan()
{
	int x;
	char c = *(in++);
	bool minus = 0;
	while (!isdigit(c) && c != '-')c = *(in++);
	if (c == '-')minus = 1, c = *(in++);
	x = c - '0';
	while (isdigit(c = *(in++)))x = x * 10 + c - '0';
	if (minus)x = -x;
	return x;
}

int head[maxn];
int p[maxn << 1];
int next1[maxn << 1];
int t[maxn << 1];
int edgecnt;

int u1[maxn];
int v1[maxn];

int father[maxn];

int DfsOrder[maxn];
int DfsOrderNumber;
int FirstDfsOrder[maxn];
int FirstDfsOrderNumber;
int fatherEdge[maxn];

int childSizeMax[maxn];
int maxChildEdge[maxn];
int heavyEdge[maxn << 1];
int size1[maxn];

int topChainPoint[maxn];
int pointDeep[maxn];
int dep[maxn];
int lcaUV[maxn];

int w[maxn];
int cnt[maxn << 1];
int pointCnt[maxn];

void addedge(int u, int v, int w)// 添加边(u,v)
{
	edgecnt++;
	p[edgecnt] = v;
	next1[edgecnt] = head[u];
	t[edgecnt] = w;
	head[u] = edgecnt;
}

void DFS0(int point)
{
	FirstDfsOrder[FirstDfsOrderNumber] = point;
	FirstDfsOrderNumber++;
	int nextEdge = head[point];
	while (nextEdge != 0)
	{
		int nextPoint = p[nextEdge];
		if (father[nextPoint] == 0)
		{
			fatherEdge[nextPoint] = nextEdge;
			father[nextPoint] = point;
			DFS0(nextPoint);
		}
		nextEdge = next1[nextEdge];
	}
	DfsOrder[DfsOrderNumber] = point;
	DfsOrderNumber++;
}

void NotDfs(int n)
{
	for (int i = 0; i < DfsOrderNumber; i++)
	{
		int point = DfsOrder[i];
		if (maxChildEdge[point] != 0)
		{
			heavyEdge[maxChildEdge[point]] = 1;
		}
		size1[point]++;
		int fatherPoint = father[point];
		if (fatherPoint != -1)
		{
			size1[fatherPoint] += size1[point];
			if (size1[point] > childSizeMax[fatherPoint])
			{
				childSizeMax[fatherPoint] = size1[point];
				maxChildEdge[fatherPoint] = fatherEdge[point];
			}
		}
	}
}

void NotDfs1()
{
	for (int i = 0; i < FirstDfsOrderNumber; i++)
	{
		int point = FirstDfsOrder[i];
		int fatherPoint = father[point];
		if (fatherPoint != -1)
		{
			pointDeep[point] = pointDeep[fatherPoint] + 1;
			dep[point] = dep[fatherPoint] + t[fatherEdge[point]];
			if (heavyEdge[fatherEdge[point]] == 1)
			{
				topChainPoint[point] = topChainPoint[fatherPoint];
			}
			else
			{
				topChainPoint[point] = point;
			}
		}
	}
}

inline int LCA(int point1, int point2)
{
	int ans = 0;
	int f1 = topChainPoint[point1];
	int f2 = topChainPoint[point2];
	while (f1 != f2)
	{
		if (pointDeep[f1] < pointDeep[f2])
		{
			swap(point1, point2);
			swap(f1, f2);
		}
		if (f1 != point1) point1 = f1;
		else point1 = father[point1];
		f1 = topChainPoint[point1];
		f2 = topChainPoint[point2];
	}
	ans = point1;
	if (pointDeep[point1] > pointDeep[point2])
	{
		ans = point2;
	}
	return ans;
}

void NotDFS4()
{
	for (int i = 0; i < DfsOrderNumber; i++)
	{
		int point = DfsOrder[i];
		int fatherPoint = father[point];
		if (fatherPoint != -1)
		{
			pointCnt[fatherPoint] += pointCnt[point];
			cnt[fatherEdge[point]] = pointCnt[point];
		}
	}
}

int Test1(int ans, int m, int n, int maxW)
{
	for (int i = 0; i <= n; i++)
	{
		pointCnt[i] = 0;
	}
	for (int i = 0; i <= 2 * n; i++)
	{
		cnt[i] = 0;
	}
	int tempSize = 0;
	for (int i = 0; i < m; i++)
	{
		if (w[i]>ans)
		{
			tempSize++;
			pointCnt[u1[i]]++;
			pointCnt[v1[i]]++;
			pointCnt[lcaUV[i]] -= 2;
		}
	}
	if (tempSize == 0) return 1;
	NotDFS4();
	for (int i = 0; i <= 2 * n; i++)
	{
		if (cnt[i] == tempSize && maxW - t[i] <= ans)
		{
			return 1;
		}
	}
	return 0;
}

int main()
{
	freopen("transport.in", "r", stdin);
	freopen("transport.out", "w", stdout);
	fread(in, 1, 10000000, stdin);
	int n, m;
	n = scan();
	m = scan();
	int maxEdgeLength = 0;
	for (int i = 1; i < n; i++)
	{
		int u = scan();
		int v = scan();
		int w = scan();
		maxEdgeLength = max(maxEdgeLength, w);
		addedge(u, v, w);
		addedge(v, u, w);
	}
	for (int i = 0; i < m; i++)
	{
		u1[i] = scan();
		v1[i] = scan();
		if (u1[i]>v1[i]) swap(u1[i], v1[i]);
	}
	father[1] = -1;
	DFS0(1);
	NotDfs(n);
	NotDfs1();
	int maxW = 0;
	for (int i = 0; i < m; i++)
	{
		lcaUV[i] = LCA(u1[i], v1[i]);
		w[i] = dep[u1[i]] + dep[v1[i]] - 2 * dep[lcaUV[i]];
		maxW = max(maxW, w[i]);
	}
	int left1 = maxW - maxEdgeLength - 1;
	int right1 = maxW;
	while (right1 - left1 > 1)
	{
		int mid = (right1 + left1) >> 1;
		if (Test1(mid, m, n, maxW)) right1 = mid;
		else left1 = mid;
	}
	printf("%d\n", right1);
	return 0;
}