HDU 4916 树分治

Mart Master II

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 285    Accepted Submission(s): 94

Problem Description

Trader Dogy lives in city S, which consists of n districts. There are n - 1 bidirectional roads in city S, each connects a pair of districts. Indeed, city S is connected, i.e. people can travel between every pair of districts by roads.

In some districts there are marts founded by Dogy’s competitors. when people go to marts, they’ll choose the nearest one. In cases there are more than one nearest marts, they’ll choose the one with minimal city number.

Dogy’s money could support him to build only one new marts, he wants to attract as many people as possible, that is, to build his marts in some way that maximize the number of people who will choose his mart as favorite. Could you help him?

Input

There are multiple test cases. Please process till EOF.

In each test case:

First line: an integer n indicating the number of districts.

Next n - 1 lines: each contains three numbers bi, ei and wi, (1 ≤ bi,ei ≤ n,1 ≤ wi ≤ 10000), indicates that there’s one road connecting city bi and ei, and its length is
wi.

Last line : n(1 ≤ n ≤ 105) numbers, each number is either 0 or 1, i-th number is 1 indicates that the i-th district has mart in the beginning and vice versa.

Output

For each test case, output one number, denotes the number of people you can attract, taking district as a unit.

Sample Input

5
1 2 1
2 3 1
3 4 1
4 5 1
1 0 0 0 1
5
1 2 1
2 3 1
3 4 1
4 5 1
1 0 0 0 0
1
1
1
0

Sample Output

2
4
0
1

Source

2014 ACM/ICPC Asia Regional Xi‘an Online

题目讲解:http://www.itnose.net/detail/6118094.html

代码:

/* ***********************************************
Author :rabbit
Created Time :2014/11/1 22:13:28
File Name :6.cpp
************************************************ */
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-8
#define pi acos(-1.0)
typedef long long ll;
const int maxn=100100;
struct Edge{
	int next,to,w;
}edge[maxn*2];
int head[maxn],tot;
void init(){
	tot=0;
	memset(head,-1,sizeof(head));
}
inline void addedge(int u,int v,int w){
	edge[tot].to=v;
	edge[tot].next=head[u];
	edge[tot].w=w;
	head[u]=tot++;
}
int size[maxn],vis[maxn],fa[maxn],que[maxn];
int TT;
inline int getroot(int u){
	int Min=maxn,root=0;
	int l,r;
	que[l=r=1]=u;
	fa[u]=0;
	for(;l<=r;l++)
		for(int i=head[que[l]];i!=-1;i=edge[i].next){
			int v=edge[i].to;
			if(v==fa[que[l]]||vis[v]==TT)continue;
			que[++r]=v;
			fa[v]=que[l];
		}
	for(l--;l;l--){
		int x=que[l],Max=0;
		size[x]=1;
		for(int i=head[x];i!=-1;i=edge[i].next){
			int v=edge[i].to;
			if(v==fa[x]||vis[v]==TT)continue;
			Max=max(Max,size[v]);
			size[x]+=size[v];
		}
		Max=max(Max,r-size[x]);
		if(Max<Min){
			Min=Max;root=x;
		}
	}
	return root;
}
int ans[maxn];
pair<int,int> pp[maxn],np[maxn];
int dis[maxn],type[maxn];
inline void go(int u,int pre,int w,int tt){
	int l,r;
	que[l=r=1]=u;
	fa[u]=pre;dis[u]=w;
	for(;l<=r;l++)
		for(int i=head[que[l]];i!=-1;i=edge[i].next){
			int v=edge[i].to;
			if(v==fa[que[l]]||vis[v]==TT)continue;
			que[++r]=v;
			fa[v]=que[l];
			dis[v]=dis[que[l]]+edge[i].w;
		}
	int cnt=0;
	for(int i=1;i<=r;i++){
		int x=que[i];
		pp[cnt++]=make_pair(np[x].first-dis[x],np[x].second);
	}
	sort(pp,pp+cnt);
	for(int i=1;i<=r;i++){
		int x=que[i];
		if(type[x])continue;
		int id=lower_bound(pp,pp+cnt,make_pair(dis[x],x))-pp;
		ans[x]+=(cnt-id)*tt;
	}
}
void solve(int u){
	int root=getroot(u);
	vis[root]=TT;
	go(root,0,0,1);
	for(int i=head[root];i!=-1;i=edge[i].next){
		int v=edge[i].to;
		if(vis[v]==TT)continue;
		go(v,root,edge[i].w,-1);
	}
	for(int i=head[root];i!=-1;i=edge[i].next){
		int v=edge[i].to;
		if(vis[v]==TT)continue;
		solve(v);
	}
}
bool ff[maxn];
int main()
{
     //freopen("data.in","r",stdin);
     //freopen("data.out","w",stdout);
     int n;
	 memset(vis,0,sizeof(vis));
	 TT=0;
	 while(~scanf("%d",&n)){
		 init();
		 int u,v,w;
		 for(int i=1;i<n;i++){
			 scanf("%d%d%d",&u,&v,&w);
			 addedge(u,v,w);
			 addedge(v,u,w);
		 }
		 for(int i=1;i<=n;i++)scanf("%d",&type[i]);
		 queue<int> q;
		 for(int i=1;i<=n;i++)
			 if(type[i]){
				 np[i]=make_pair(0,i);
				 ff[i]=true;
				 q.push(i);
			 }
			 else {
				 np[i]=make_pair(INF,0);
				 ff[i]=false;
			 }
		 while(!q.empty()){
			 int u=q.front();
			 q.pop();
			 ff[u]=0;
			 for(int i=head[u];i!=-1;i=edge[i].next){
				 v=edge[i].to;
				 pair<int,int> tmp=make_pair(np[u].first+edge[i].w,np[u].second);
				 if(tmp<np[v]){
					 np[v]=tmp;
					 if(!ff[v]){
						 ff[v]=1;
						 q.push(v);
					 }
				 }
			 }
		 }
		 TT++;
		 for(int i=1;i<=n;i++)ans[i]=0;
		 solve(1);
		 int ret=0;
		 for(int i=1;i<=n;i++)ret=max(ret,ans[i]);
		 cout<<ret<<endl;
	 }
     return 0;
}
时间: 2024-12-18 18:04:23

HDU 4916 树分治的相关文章

HDU 5102 树分治

The K-th Distance Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 202    Accepted Submission(s): 50 Problem Description Given a tree, which has n node in total. Define the distance between two

hdu 4868 树分治

#include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<iostream> #include<queue> using namespace std; const int M = 60005; struct Edge{ int v, next, w; }edge[M << 2], ee[M ]; map<int, int

HDU 4812 D Tree 树分治+逆元处理

D Tree Problem Description There is a skyscraping tree standing on the playground of Nanjing University of Science and Technology. On each branch of the tree is an integer (The tree can be treated as a connected graph with N vertices, while each bran

HDU 4916 Count on the path

题意: 给定一棵树和m个询问  每个询问要求回答不在u和v两节点所形成的路径上的点的最小标号 思路: 一开始以为是LCA-  不过T了好几次-  后来发现不用LCA也可做 考虑每个询问u和v  如果他们的lca不是1  则1一定是答案  不过求lca会T  那么我们只需要在遍历树的时候给节点染色  染的颜色就是1的儿子的颜色  如果x这个点在y的子树中(y是1的儿子)那么他的颜色就是y 染完色后我们考虑答案是如何构成的 如图所示  答案即是  红色  蓝色  绿色的子树中节点的最小值  那么我们

poj 1744 tree 树分治

Tree Time Limit: 1000MS   Memory Limit: 30000K       Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dist(u,v)=The min distance between node u and v. Give an integer k,for every pair (u,v) of ve

COJ 0970 WZJ的数据结构(负三十)树分治

WZJ的数据结构(负三十) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计一个数据结构,回答M次操作. 1 x v:对于树上的每一个节点y,如果将x.y在树上的距离记为d,那么将y节点的权值加上d*v. 2 x:询问节点x的权值. 输入 第一行为一个正整数N.第二行到第N行每行三个正整数ui,vi,wi.表示一条树边从ui到vi,距离为wi.第N+1行为一个正整数M.最后

Codeforces 321C Ciel the Commander 树分治裸题

题目链接 题意: 给定一棵树,要用字母A-Z 填到每个节点上 字母可以无限使用,但A至多只能用一次 目标:对于任意两个相同字母的节点,他们之间的路径上必须有至少一个节点的字母比他们小 例如:在两个C之间至少要有一个A 或者一个B 问: 输出填涂方案. 树分治即可,最多支持2^25个节点,不会无解. #include <iostream> #include <string> #include <vector> #include <cstring> #inclu

hdu 3333 树状数组+离线处理

http://acm.hdu.edu.cn/showproblem.php?pid=3333 不错的题,想了很久不知道怎么处理,而且答案没看懂,然后找个例子模拟下别人的代码马上懂了---以后看不懂的话就拿个例子模拟下别人的代码 举个例子:1 3 3 5 3 5 查询 a, 2 4 b, 2 5 最初是这么想的:对于a查询,倘若把第二个数第三个数变成1个3,那么到b查询,又出现了两个3,再做处理似乎还是O(n),而且如果先出现2,5查询,后出现2,4查询,那么还需要把删除的数补回来.....o(╯

Hdu 3887树状数组+模拟栈

题目链接 Counting Offspring Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1757    Accepted Submission(s): 582 Problem Description You are given a tree, it’s root is p, and the node is numbered fr