问题 C: 约会

问题 C: 约会

时间限制: 2 Sec  内存限制: 256 MB

题目描述

输入

输出

样例输入

4
1 2
1 3
2 4
1
2 3

样例输出

1

提示




T掉的树剖


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#define V 100009
#define LL long long 
using namespace std;
int n,a[V],f[V];
struct da
{
int to,next;
}Edge[V*2];
deque<int>Q[2];
int head[V],tot,siz[V],son[V],dep[V],top[V],id[V],cnt,ps[V];
inline void add(int x,int y)
{
	Edge[tot].to=y;
	Edge[tot].next=head[x];
	head[x]=tot++;
}
inline void dfs1(int x)
{
	int v;
	siz[x]=1;
	for(int i=head[x];i!=-1;i=Edge[i].next)
	{
		v=Edge[i].to;
		if(v!=f[x])
		{
			f[v]=x;
			dep[v]=dep[x]+1;
			dfs1(v);
			siz[x]+=siz[v];
			if(siz[v]>siz[son[x]])
			son[x]=v;
		}
	}
}
inline void dfs2(int x,int ss)
{
	int v;
	id[x]=++cnt;
	ps[cnt]=x;
	top[x]=ss;
	if(son[x])dfs2(son[x],ss);
	for(int i=head[x];i!=-1;i=Edge[i].next)
	{
		v=Edge[i].to;
		if(v!=f[x]&&v!=son[x])
		dfs2(v,v);
	}
}
inline int mdx(int sbb,int mdd,int x,int y,int num)
{
	if((sbb-mdd)%2!=0)return 0;
	int xx,yy;
	xx=(sbb-mdd)/2;
	y=Q[0].front();Q[0].pop_front();
	while(dep[y]-dep[x]<xx)
	{
		xx-=(dep[y]-dep[x]);
		x=y;
		y=Q[0].front();
	}
	xx=id[x]+xx;
	xx=ps[xx];
	return siz[xx]-siz[son[xx]];
}
inline int mdy(int sbb,int mdd,int x,int y,int num)
{
	if((mdd-sbb)%2!=0)return 0;
	int xx,yy;
	xx=(sbb-mdd)/2;
	   y=Q[1].front();Q[1].pop_front();
	while(dep[y]-dep[x]<xx)
	{
		xx-=(dep[y]-dep[x]);
		x=y;
		y=Q[1].front();
	}
	xx=id[x]+xx;
	xx=ps[xx];
	return siz[xx]-siz[son[x]];
}
inline int QQ(int x,int y)
{
	int fx=top[x],fy=top[y];
	int num=0;
	Q[0].push_front(x);
	Q[1].push_front(y);
	int sbb=dep[x],mdd=dep[y],mb;
	while(fx!=fy)
	{
		if(dep[fx]<dep[fy])
		{
			 num^=1;
			 swap(x,y);
			 swap(fx,fy); 
		} 
		x=f[x];
		Q[num].push_front(x);
		fx=top[x];
	}
	if(dep[x]>dep[y])
	{
	 num^=1;
	 swap(x,y);
    }
    Q[num].pop_front();
    sbb=sbb-dep[x];
    mdd=mdd-dep[x];
    if(sbb==mdd)
    return siz[x]-siz[son[x]]-siz[top[Q[num].front()]]+dep[x]-1;
    else if(sbb>mdd)
    return mdx(sbb,mdd,x,y,num);
    else
	return mdy(sbb,mdd,x,y,num);
}
inline int read()
{
	int mdd=0,sbb=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-')
		sbb=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		mdd=mdd*10+ch-'0';
		ch=getchar();
	}
	return mdd*sbb;

}
int main()
{
   //freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);
  //freopen("bcatch.in","r",stdin);freopen("bcatch.out","w",stdout);
  memset(head,-1,sizeof(head));
   //n=read();
   scanf("%d",&n);
   int x,y;
   for(int i=1;i<n;i++)
   {
     scanf("%d%d",&x,&y);
     add(x,y);
     add(y,x);
   }
   dep[1]=1;
   dfs1(1);
   dfs2(1,1);
   int m;
   m=read();
   while(m--)
   {
    scanf("%d%d",&x,&y);
	//x=read();
	  // y=read();
	  printf("%d\n",QQ(x,y));
	  //cout<<QQ(x,y)<<endl;
	  Q[0].clear();
	  Q[1].clear();
   }
   
}



过了的倍增


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#define V 100009
#define LL long long 
using namespace std;
int n,a[V],f[V];
struct da
{
	int to,next;
}Edge[V*2];
deque<int>Q[2];
int head[V],tot,siz[V],dep[V],d[V][30];
inline void add(int x,int y)
{
	Edge[tot].to=y;
	Edge[tot].next=head[x];
	head[x]=tot++;
}
inline void dfs1(int x)
{
	int v;
	siz[x]=1;
	for(int i=head[x];i!=-1;i=Edge[i].next)
	{
		v=Edge[i].to;
		if(v!=f[x])
		{
			f[v]=x;
			dep[v]=dep[x]+1;
			dfs1(v);
			siz[x]+=siz[v];
		}
	}
}
inline void RMQ()
{
	for(int i=1;i<=n;i++)d[i][0]=f[i];
	for(int j=1;(1<<j)<=n;j++)
	 for(int i=1;i<=n;i++)
	  if(d[i][j-1])
	 d[i][j]=d[d[i][j-1]][j-1];
}
inline int lca(int x,int y)
{
	int i,j;
	if(dep[x]<dep[y])swap(x,y);
	for(i=0;(1<<i)<=dep[x];i++);
	i--;
	for(j=i;j>=0;j--)
	if(dep[x]-(1<<j)>=dep[y])
	x=d[x][j];
	if(x==y)return x;
	//cout<<dep[x]<<"  "<<dep[y]<<endl;
	for(j=i;j>=0;j--)
	{
		if(d[x][j]&&d[x][j]!=d[y][j])
		{
			x=d[x][j];
			y=d[y][j];
		}
	}
   //cout<<x<<" "<<y<<endl;
	return f[x];
}
int QQ(int x,int y)
{
	int i,j;
	int z=lca(x,y);
	int xx=dep[x],yy=dep[y],zz=dep[z];
	if((xx-zz+yy-zz)%2!=0)return 0;
	if(x==y)return n;
	if(xx==yy)
	{
			for(i=0;(1<<i)<=xx;i++);
				i--;
			for(j=i;j>=0;j--)
			if(dep[x]-(1<<j)>=zz+1)
			x=d[x][j];
			
			for(i=0;(1<<i)<=yy;i++);
				i--;
			for(j=i;j>=0;j--)
			if(dep[y]-(1<<j)>=zz+1)
			y=d[y][j];
			//cout<<x<<" #$% "<<y<<"  "<<z<<endl;
			return n-siz[x]-siz[y];
		    
	}
	if(dep[x]<dep[y])swap(x,y);
	int ww=(xx+yy-2*zz)/2;
	ww=dep[x]-ww;
	for(i=0;(1<<i)<=dep[x];i++);
	i--;
	for(j=i;j>=0;j--)
	if(dep[x]-(1<<j)>=ww+1)
	x=d[x][j];
//	cout<<" $%^ !!"<<siz[f[x]]<<"  "<<siz[x]<<"  "<<f[x]<<" "<<x<<endl;
	return siz[f[x]]-siz[x];
}
int main()
{
   //freopen("in.txt","r",stdin);freopen("22.txt","w",stdout);
  //freopen("bcatch.in","r",stdin);freopen("bcatch.out","w",stdout);
  memset(head,-1,sizeof(head));
   //n=read();
   scanf("%d",&n);
   int x,y;
   for(int i=1;i<n;i++)
   {
   	  //x=read();
   	  //y=read();
   	  scanf("%d%d",&x,&y);
   	  //if(x*y==12)
   	  //cout<<x<<" @@ "<<y<<endl<<endl;
   	  add(x,y);
   	  add(y,x);
   }
   dep[1]=1;
   dfs1(1);
   RMQ();
   int m;
   scanf("%d",&m);
   while(m--)
   {
   	scanf("%d%d",&x,&y);
	printf("%d\n",QQ(x,y));
  }
   
}



<p><fontface>本程序基于新云网站管理系统V3.0.0.610修改美化,适合做文章、新闻、信息类综合网站,含6条采集规则,可自动抓取信息,因压缩包大小问题,删除生成的内容网页和文中图片,其余数据完整。</font></p> <p><fontface>采用新云系统成熟、稳定地技术ASP+Access/SQL修改而成,通过它,您可以很方便地管理自己网站。</font></p> <p><fontface>修改者声明:你可以任意修改程序,请保留我一个友情链接。 链接地址:http://www.ipaoniu.com/</font></p> <p><fontface>功能特点如下:(来自新云的官方说明)</font></p> <p><fontface>多频道管理,无限制频道克隆,支持频道二级域名绑定功能,文章内容自动分页;</font></p> <p><fontface>全站生成HTML页面;增加系统安全性,自由设置生成HTML文件扩展名和存放目录,内容自动分页。</font></p> <p><fontface>用户管理,多用户管理分权限发布、管理软件信息;用户短信、收藏功能,会员在线充值,网银在线支付;</font></p> <p><fontface>下载模块,支持计点会员和包月会员下载,反点等功能,无限制添加下载服务器,下载点数设置,添加软件只需要填写软件名称;</font></p> <p><fontface>强大的文章、软件采集功能,文章采集的同时可以选择是否下载图片到本地及分页采集; 其它模块,留言、友情连接自助申请,上传水印,内容关键字功能。</font></p> <p><fontface>后台登陆地址:/admin/admin_login.asp 默认管理员:admin 密码:ipaoniu</font></p>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值