记录编号 95637 评测结果 AAAAAAAAAA
题目名称 [NOIP 2012]疫情控制 最终得分 100
用户昵称 Gravatardigital-T 是否通过 通过
代码语言 C++ 运行时间 0.294 s
提交时间 2014-04-08 09:47:43 内存使用 7.18 MiB
显示代码纯文本
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<map>
using namespace std;

#define maxn 100007

struct atype
{
    int x, y;
};

multimap<int,int> tmap;
multimap<int,int>::iterator iter;

int now;
int n, m, e;
int f[maxn];
int g[maxn], h[maxn];
int a[maxn];
int b[maxn], c[maxn];
atype d[maxn];
int nd;

int edge[maxn];
int goal[maxn*2], next[maxn*2], cost[maxn*2];
vector<int> army[maxn];

void contact(int u, int v, int w)
{
	++e; goal[e] = v; cost[e] = w;
	next[e] = edge[u]; edge[u] = e;
	++e; goal[e] = u; cost[e] = w;
	next[e] = edge[v]; edge[v] = e;
}

void dfs(int u, int fa)
{
	int v, j;
	j = edge[u];
	while (j) {
		v = goal[j];
		if (v != fa) {
			f[v] = f[u]+cost[j];
			dfs(v,u);
		}
		j = next[j];
	}
	if (g[u] > 0) {
		for (j = 1; j <= g[u]; ++j)
			army[now].push_back(f[u]);
    }
}
int find(int t)
{
	int l, r, mid;
	l = 2; r = a[0];
	while (l+1 < r) {
		mid = (l+r)/2;
		if (t <= f[a[mid]]) r = mid;
		else l = mid;
	}
	if (t <= f[a[l]]) return l;
	return r;
}
int findnum(int u, int t)
{
	int l, r, mid;
	r = army[u].size();
	if (r == 0) return 0;
	l = 0; --r;
	while (l+1 < r) {
		mid = (l+r)/2;
		if (army[u][mid] <= t) l = mid;
		else r = mid;
	}
	if (army[u][r] <= t) return r+1;
	else if (army[u][l] <= t) return l+1;
	return 0;
}
void dfs2(int u, int fa)
{
	int v,j;
	a[++a[0]] = u;
	if (g[u] > 0) {
		j = find(f[u]-now);
		h[a[j]] += g[u];
	}
	j = edge[u];
	while (j) {
		v = goal[j];
		if (v != fa) {
			dfs2(v,u);
		}
		j = next[j];
	}
	--a[0];
}
bool cmp(int p, int q)
{
	return (p > q);
}
bool cmpd(atype p, atype q)
{
	return (p.y < q.y);
}
bool checkblock(int u, int fa)
{
	int j, v;
	bool ok;
	ok = false;
	j = edge[u];
	while (j) 
	{
		v = goal[j];
		if (v != fa) 
		{
			ok = true;
			if (h[v] == 0 && !checkblock(v,u))
				return false;
		}
		j = next[j];
	}
	return ok;
}
bool check(int time)
{
	int i, j, k, u, v, t;
	bool ok;
	bool tok;
	
	memset(h,0,sizeof(h));
	a[0] = 0; 
	now = time;
	dfs2(1,0);

	b[0] = 0; c[0] = 0; nd = 0;
	u = 1; j = edge[u];    
	while (j) 
	{
		v = goal[j];
		ok = checkblock(v,1);
		tok = false;
		if (!ok && h[v] == 0)
			c[++c[0]] = cost[j];
		else {
			k = findnum(v,time-cost[j]);
			if (h[v] == k && !ok) 
			{
				--k;
				tok = true;
			}
			t = 0;
			while (k > 0) 
			{
				--k;
				b[++b[0]] = army[v][t++]-time+cost[j];
			}
			if (tok) 
			{
				++nd;
				d[nd].x = cost[j];
				d[nd].y = army[v][t]-time+cost[j];
				++t;
			}
		}
		j = next[j];
	}
    
	tmap.clear();
	for (i = 1; i <= b[0]; ++i)
		tmap.insert(multimap<int,int>::value_type(-b[i],0));
	for (i = 1; i <= nd; ++i) 
	{
		iter = tmap.lower_bound(d[i].x);
		if (iter == tmap.end()) continue;
		if (d[i].y < -iter->first) 
		{
			tmap.erase(iter);
			tmap.insert(multimap<int,int>::value_type(-d[i].y,0));
		}
	}
    
	iter = tmap.begin();
	for (i = 1; i <= b[0]; ++i)
	{
		b[i] = -iter->first;
		iter++;
	}
    
	sort(b+1,b+b[0]+1);
	sort(c+1,c+c[0]+1,cmp);
	if (b[0] < c[0]) return false;
	for (i = 1; i <= c[0]; ++i)
		if (c[i]+b[i] > 0)
			return false;
	return true;
}
int main()
{
	freopen("blockade.in","r",stdin);
	freopen("blockade.out","w",stdout);
	
	int i, j;
	int u,v,w;
	int l,r,mid;
	
	memset(f,0,sizeof(f));
	memset(g,0,sizeof(g));
	e = 1;
	memset(edge,0,sizeof(edge));
	
	scanf("%d",&n);
	l = 0; r = 0;
	for (i = 1; i < n; ++i) {
		scanf("%d%d%d",&u,&v,&w);
		contact(u,v,w);
		if (w > r) r = w;
	}
	scanf("%d",&m);
	for (i = 1; i <= m; ++i) {
		scanf("%d",&u);
		++g[u];
	}

	j = edge[1];
	while (j) {
		v = goal[j];
		now = v;
		army[now].clear();
		dfs(v,1);
		sort(army[now].begin(),army[now].end());
		w = army[now].size();
		if (w > 0 && army[now][w-1] > r) {
			r = army[now][w-1];
		}
		j = next[j];
	}
	r += r+r;
	
	while (l+1 < r) {
		mid = (l+r)/2;
		if (check(mid)) r = mid;
		else l = mid;
	}
	if (!check(l))
		if (!check(r)) printf("%d\n",-1);
		else printf("%d\n",r);
	else
		printf("%d\n",l);
	return 0;
}