码迷,mamicode.com
首页 > 其他好文 > 详细

P4149 [IOI2011]Race

时间:2018-06-03 17:28:16      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:\n   div   路径   work   mes   span   style   getc   family   

题意:给一棵树,每条边有权。求一条简单路径,权值和等于 K ,且边的数量最小。

总结:这个题直接做不好找边数最小,可以转化为判定性问题,ans[i]表示权值和等于K的边的数量为i的路径个数,然后直接点分统计

 

#include<bits/stdc++.h>

using namespace std;
const int maxn = 400005;

int n, k, root, tot, cnt = 1, head[maxn], f[maxn];
int siz[maxn], ans[1000005], sum, vis[maxn], deep[maxn], dis[maxn];
struct Node{
	int v, nxt, w;
} G[maxn]; 
struct DATA {
	int dep, l;
} a[maxn];
void ins(int u, int v, int w) {
	G[cnt] = (Node) {v, head[u], w}; head[u] = cnt++;
}
int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < ‘0‘ || ch > ‘9‘) { if(ch == ‘-‘) f = -1; ch = getchar();}
	while(ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - 48; ch = getchar();}
	return x * f;
}

void Getrt(int x, int fa) {
	f[x] = 0; siz[x] = 1;
	for (int i = head[x]; i; i = G[i].nxt) {
		int v = G[i].v;
		if(v == fa || vis[v]) continue;
		Getrt(v, x);
		siz[x] += siz[v];
		f[x] = max(f[x], siz[v]);
	} f[x] = max(f[x], sum - siz[x]);
	if(f[x] < f[root]) root = x;
}
bool cmp(DATA a, DATA b) {
	return a.l < b.l;
}
void Getdp(int x, int fa) {
	a[++tot] = (DATA) {deep[x], dis[x]};
	for (int i = head[x]; i; i = G[i].nxt) {
		int v = G[i].v;
		if(vis[v] || v == fa) continue;
		deep[v] = deep[x] + 1;
		dis[v] = dis[x] + G[i].w;
		Getdp(v, x);
	}
}
void calc(int x, int w, int ww, int sig) {
	deep[x] = ww; dis[x] = w; tot = 0; Getdp(x, 0);
	sort(a + 1, a + tot + 1, cmp);
	int l = 1, r = tot;
	for (; l <= r; ++l) {
		while(l < r && a[l].l + a[r].l > k) --r;
		for (int i = r; a[i].l + a[l].l == k; --i) ans[a[i].dep + a[l].dep] += sig; 
	}
}
void work(int x) {
	vis[x] = 1; calc(x, 0, 0, 1);
	for (int i = head[x]; i; i = G[i].nxt) {
		int v = G[i].v;
		if(vis[v]) continue;
		calc(v, G[i].w, 1, -1);
		root = 0; sum = siz[v];
		Getrt(v, 0); work(root);
	}
}

int main() {
	n = read(); k = read();
	for (int i = 1; i <= n - 1; ++i) {
		int x, y, z; x = read(); y = read(); z = read(); 
		x++; y++;
		ins(x, y, z); ins(y, x, z);
	}
	root = 0; f[0] = 0x7fffff; sum = n;
	Getrt(1, 0); work(root);
	for (int i = 1; i <= n; ++i) {
		if(ans[i]) {
			printf("%d\n", i); return 0;
		}
	} printf("-1");
	return 0;
}

 

  

 

P4149 [IOI2011]Race

标签:\n   div   路径   work   mes   span   style   getc   family   

原文地址:https://www.cnblogs.com/oi-forever/p/9129445.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!