#include"cstdio"
#include"iostream"
#include"set"
#include"queue"//hdu4912
#include"string.h"
using namespace std;
#define N 100010//由最下面的开始选,这样尽量多的选而且不重复,样例2中不是4,5,而是4,2,5,
struct Edge
{//样例二中,不是6,7,而是,3,6,7
int from, to, nex;
}edge[2*N];//nex是同一个父节点的上一条边的边号
int head[N],edgenum,dis[N],fa[N][20],dep[N],n,m; //fa[i][x] 是i的第2^x个父亲(如果超过范围就是根)
struct node
{
int l, r, lca;
}q[N];
int vis[N], tim;
void add(int u,int v)
{
Edge E={u,v,head[u]};
edge[edgenum] = E;
head[u]=edgenum++; //headu是头是U的边的序号
}
void bfs(int root)//就是这里的循环原理
{
queue<int> q;
fa[root][0]=root;dep[root]=0;dis[root]=0;//深度为0
q.push(root);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=1;i<20;i++)fa[u][i]=fa[fa[u][i-1]][i-1];//一层一层的向上找祖先,给出每一段距离的祖先
//20是差不多定的吧
for(int i=head[u]; ~i;i=edge[i].nex)//i!=-1,不断搜寻 他的子节点那一层
{
int v=edge[i].to;if(v==fa[u][0])continue;//找到边是u的连边就不执行
dep[v]=dep[u]+1;dis[v]=dis[u]+1;fa[v][0]=u;//画图就行,因为是一层一层下来
//所以深度加一,U父v子
q.push(v);//好吧,他的搜寻很巧
}
}
}
int Lca(int x,int y){//比较深度
if(dep[x]<dep[y])swap(x,y);//令X为深度大的
for(int i=0;i<20;i++)if((dep[x]-dep[y])&(1<<i))x=fa[x][i];//找其父节点,找到一个深度相同的
if(x==y)return x;//相同公共祖先就是自己
for(int i=19;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];//一层一层各自找自己的父亲,
//看到了哪层是一样的
return fa[x][0];//返回LCA
}
void init()
{memset(head, -1, sizeof head); edgenum = 0;}//简单的初始化
bool cmp(node a, node b)
{
return dep[a.lca]>dep[b.lca];//返回lca深度的大小比较,从深度大的开始贪心
}
int main()
{
int i, j, u, v;
memset(vis, 0, sizeof vis);
tim = 1;
while(~scanf("%d %d",&n,&m))
{
init();
tim++;//第几组case
for(i = 1; i < n; i++)
{
scanf("%d %d",&u,&v);
add(u, v);
add(v, u);
}
bfs(1);//根节点搜寻
for(i = 1; i <= m; i++)
{
scanf("%d %d",&q[i].l, &q[i].r);
q[i].lca = Lca(q[i].l, q[i].r);//返回他们的最近公共祖先
}
sort(q+1, q+1+m, cmp);//按公共祖先倒叙贪心选择
int ans = 0;
for(i = 1; i <= m; i++)
{
int lca = q[i].lca;
u = q[i].l, v = q[i].r;
if(vis[lca] == tim)continue;
bool ok = true;
if(u == lca)
{
while(v!=lca)
{
if(vis[v]==tim){ok = false;break;}
v = fa[v][0];
}
if(ok)
{
ans++;
v = q[i].r;
while(v!=lca)
vis[v]==tim;
v = fa[v][0];
}
vis[lca] = tim;
}
}
else if(v==lca)
{
while(u!=lca)
{
if(vis[u]==tim){ok=false;break;}
u = fa[u][0];
}
if(ok)
{
ans++;
u = q[i].l;
while(u!=lca){
vis[u]==tim;
u = fa[u][0];
}
vis[lca] = tim;
}
}
else {
while(v!=lca){
if(vis[v]==tim){ok = false;break;}
v = fa[v][0];
}
if(ok)
while(u!=lca){
if(vis[u]==tim){ok=false;break;}
u = fa[u][0];
}
if(ok)
{
ans++;
u = q[i].l, v = q[i].r;
while(v!=lca){
vis[v]==tim;
v = fa[v][0];
}
while(u!=lca){
vis[u]==tim;
u = fa[u][0];
}
vis[lca] = tim;
}
}
}
cout<<ans<<endl;
}
return 0;
}
HDU4912注解
最新推荐文章于 2020-04-20 14:05:09 发布