树上路径(点分治板子题)

树上路径!!!点分治处理。(就是在树上分治处理,把树分成小树,再分成更小的树处理)

找最小的满足>=S 并且<=E的路径。

假设从随便一个点开始dfs,复杂度o(n);

然而从重心开始dfs,复杂度为O(logn);

重心:删掉这个点以后,剩余的森林的最大的size最小的点。

注意一下:合并路径时,两条路径不能有相同的祖先(处理某点,路径必须是过这个点,且路径的两端点不在同一棵子树的)。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int tp, tov[200005],  tow[200005], nex[200005], h[100005], n, m, ans = 1e9;
int siz[200005], ma[200005], mama = 1e9, vis[200050],s, e, ss, zong,root,k,zhan[2000005],top; 
void read(int &x)
{
	x = 0;
	int f  = 0;
	char c = getchar();
	while(c < '0' || c > '9')
	{
		if(c == '-') f = 1; 
		c = getchar();
	}
	while(c >= '0' && c <= '9')
	{
		x = 10 * x + c - '0';
		c = getchar();
	}
	if(f) x = -x;
}
struct node
{
	int val, zx;
};
node dis[200005];
bool cmp(const node a,const node b)
{
	return a.val < b.val; 
}
void add(int x,int y,int w)
{
	tp++;
	tov[tp] = y;
	tow[tp] = w;
	nex[tp] = h[x];
	h[x] = tp;
}
void getroot(int x,int fa)
{
	siz[x] = 1;
	ma[x] = 0;
	for(int i = h[x]; i; i = nex[i])
    {
    	int v = tov[i];
        if(vis[v] || v == fa) continue;
		getroot(v,x);	
        siz[x] += siz[v];
	   if(siz[v] > ma[x]) ma[x] = siz[v];
	}
	ma[x] = max(ma[x],zong - siz[x]);
	if(ma[x] < mama)
	{
		root = x;
		mama = ma[x];
	}
}
void jisuan(int x,int fa,int len,int ha)
{
	for(int i = h[x]; i; i = nex[i])
	{
		int v = tov[i];
		if(v == fa || vis[v]) continue;
		int made = 0;
		if(ha == - 1) made = v;else made = ha;
		dis[++s] = (node){len+tow[i],made}; 
		jisuan(v,x,len+tow[i],made);
	}
}
void solve(int x,int len)
{
	s = 1;
	dis[1] = (node){len,0}; 
	jisuan(x,x,len,-1);
    sort(dis+1,dis+1+s,cmp);
    int l = 1, r = s, temp = 0;
	for(int i = 1;  i <= s; i++)
	{
		int pos = lower_bound(dis+1,dis+1+s,(node){ss - dis[i].val,-1},cmp) - dis ;
		if(pos < i ) break;
		for(int j = pos; j <= s; j++)
	   {
	   	if(dis[i].val + dis[j].val   > e ||dis[i].val + dis[j].val   > ans ) break; 
		  if(dis[i].val + dis[j].val   >= ss && dis[i].zx != dis[j].zx)
	       {
	        ans = min(ans,dis[i].val + dis[j].val );
	        break;
	       }
	  }
	}
	/*	for(int i = 1; i <= s; i++){
		int pos = lower_bound(dis + 1, dis + 1 + s, (node) {ss - dis[i].val,-1 },cmp) - dis;
		if(pos < i)break;
		for( int k = pos; k <= s; k++){
			int c = dis[k].val + dis[i].val;
			if(c > ans || c > e)break;
			if(dis[k].zx == dis[i].zx || c < ss) continue;
			ans = min(ans, c); break;
		} 
	}
*/}
void dfs(int x)
{	
    vis[x] = 1;
 solve(x,0);
    for(int i = h[x]; i; i = nex[i])
    {
    	int v = tov[i];
    	if( vis[v]) continue;
        zong  = siz[v];
          mama = 1e9;
	 getroot(v,v);
    	dfs(root);
    }
}
int main()
{
//	freopen("path.in","r",stdin);
//  freopen("path.out","w",stdout);
	 	read(n);read(ss);read(e);
	     for(int i = 1; i <= n - 1; i++)
	     {
	     	int x,y,w;
	     	read(x);read(y);read(w);
	     	add(x,y,w);
	     	add(y,x,w);
	     }
	     mama = 1e9;
	     memset(vis,0,sizeof(vis));
	     getroot(1,1);
	     dfs(root);
	     if(ans < 1e9)printf("%d",ans);
	    else printf("-1");
	 return 0;
}

//其实我并没有想到。dfs暴力60+;

猜你喜欢

转载自blog.csdn.net/Bluelanzhan/article/details/83545810
今日推荐