Description
Input
Output
Sample Input
5 4
2 1
5 3
3 1
4 3
2
2 4
3 2
Sample Output
1
2
Solution
如果是序列,可以知道,选的点一定是尽量靠右,贪心的脑补一下就可以证明了
树上的话就是尽量选LCA,原因是一样的
按照LCA的dfs序反着做,对于每一个限制,如果它上面没有点被选择,就选择这个LCA
实现用链剖,LCT之类的都行
好像还有set加启发式合并?我不会
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define N 101000
using namespace std;
int n,m,top[N],son[N],fa[N],deep[N],last[N],next[N*5],to[N*5],tot=1,size[N],dfn[N],f[N][17],ans[N],t[N*10];
struct node{
int x,y,z;
}q[N*3];
bool cnt(node x,node y){return dfn[x.z]<dfn[y.z];}
void putin(int x,int y)
{
next[++tot]=last[x];last[x]=tot;to[tot]=y;
}
void dg1(int x)
{
for(int i=last[x];i;i=next[i])
{
int y=to[i];
if(deep[y]) continue;
deep[y]=deep[x]+1;fa[y]=f[y][0]=x;
dg1(y);
size[x]+=size[y];
if(size[y]>size[son[x]]) son[x]=y;
}
size[x]++;
}
void dg2(int x)
{
dfn[x]=++tot;
if(son[x]) top[son[x]]=top[x],dg2(son[x]);
for(int i=last[x];i;i=next[i])
{
int y=to[i];
if(top[y]) continue;
top[y]=y;dg2(y);
}
}
int lca(int x,int y)
{
if(deep[x]<deep[y]) swap(x,y);
fd(i,16,0) if(deep[f[x][i]]>=deep[y]) x=f[x][i];
fd(i,16,0) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
if(x!=y) x=fa[x];
return x;
}
void insert(int v,int i,int j,int x)
{
t[v]++;
if(i==j) return;
int mid=(i+j)/2;
if(x<=mid) insert(v*2,i,mid,x);
else insert(v*2+1,mid+1,j,x);
}
int get(int v,int i,int j,int x,int y)
{
if(i==x&&j==y) return t[v];
int mid=(i+j)/2;
if(y<=mid) return get(v*2,i,mid,x,y);
else if(x>mid) return get(v*2+1,mid+1,j,x,y);
else return get(v*2,i,mid,x,mid)+get(v*2+1,mid+1,j,mid+1,y);
}
int LCT(int x,int y)
{
int ans=0;
while(deep[x]>=deep[y])
{
int f1=top[x];
if(deep[f1]<deep[y]) f1=y;
ans=ans+get(1,1,n,dfn[f1],dfn[x]);
x=fa[f1];
if(ans) return ans;
}
return ans;
}
int main()
{
freopen("ping.in","r",stdin);
freopen("ping.out","w",stdout);
scanf("%d%d",&n,&n);n++;
fo(i,1,n-1)
{
int x,y;scanf("%d%d",&x,&y);
putin(x,y);putin(y,x);
}
deep[1]=top[1]=1;tot=0;dg1(1);dg2(1);
fo(j,1,16) fo(i,1,n) f[i][j]=f[f[i][j-1]][j-1];
scanf("%d",&m);
fo(i,1,m) scanf("%d%d",&q[i].x,&q[i].y),q[i].z=lca(q[i].x,q[i].y);
sort(q+1,q+m+1,cnt);
fd(i,m,1)
{
int jy=LCT(q[i].x,q[i].z)+LCT(q[i].y,q[i].z);
if(jy==0) ans[++ans[0]]=q[i].z,insert(1,1,n,dfn[q[i].z]);
}
printf("%d\n",ans[0]);
fo(i,1,ans[0]) printf("%d ",ans[i]);
}