猫大告诉我们,对于每坨c一样的点,有贡献的只有距离最远的两个。证明略。
那么如何求呢?只要每次取三个点,lca搞一发,保留两个就好了。
对于c不同的点怎么办呢?也搞成两个。做完了。
但是要注意计算答案时要将同颜色的两个有效点同时参与答案的计算,然后在将这两个点与最佳点比较。
我讲得不好,具体看代码。感觉这次的代码写的蛮顺眼的。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define ll long long
#define db double
#define mkp(x,y) make_pair(x,y)
#define pii pair<int,int>
#define X first
#define Y second
const int N=100005;
int he[N],to[N<<1],ne[N<<1],tot;
int n,c[N],dep[N],dad[N],son[N],sz[N],pre[N];
int m,gs[N],cs1[N],cs2[N],ans;
int lca(int x,int y){
int fx=dad[x],fy=dad[y];
while(fx!=fy)
if(dep[fx]>dep[fy])fx=dad[x=pre[fx]];
else fy=dad[y=pre[fy]];
return dep[x]<dep[y]?x:y;
}
void DFS1(int x,int e){
int y,i;
dep[x]=dep[to[e]]+1;sz[x]=1;
for(i=he[x];i;i=ne[i])if(i!=e){
pre[y=to[i]]=x;DFS1(y,i^1);
if(sz[y]>sz[son[x]])son[x]=y;
sz[x]+=sz[y];
}
}
void DFS2(int x,int e){
int y=to[e],i;
dad[x]=son[y]==x?dad[y]:x;
for(i=he[x];i;i=ne[i])if(i!=e)
DFS2(to[i],i^1);
}
int cal(int x,int y){
return dep[x]+dep[y]-(dep[lca(x,y)]<<1)+1;
}
void get(int &x,int &y,int z){
int m1=cal(x,y),m2=cal(x,z),m3=cal(y,z),mm;
mm=max(m1,max(m2,m3));
if(mm==m2)y=z;
else if(mm==m3)x=z;
/* if(c[x]==c[y]){
if(c[y]==c[z]){
mm=max(m1,max(m2,m3));
if(mm==m2)y=z;
else if(mm==m3)x=z;
}
else{
if(m2>m3)y=z;
else x=z;
}
return;
}
if(c[y]==c[z]){
if(m2>m1)y=z;
}
else if(c[x]==c[z]){
if(m3>m1)x=z;
}
else{
mm=max(m1,max(m2,m3));
if(mm==m2)y=z;
else if(mm==m3)x=z;
}*/
}
void ins(int x,int i){
if(!gs[x])gs[x]=1,cs1[x]=i;
else if(gs[x]==1)gs[x]=2,cs2[x]=i;
else get(cs1[x],cs2[x],i);
}
void add(int x,int y){
to[++tot]=y;ne[tot]=he[x];he[x]=tot;
}
int main(){
int i,x,y,Q,k;
scanf("%d%d%d",&n,&m,&Q);tot=1;
rep(i,1,n)scanf("%d",&c[i]);
rep(i,2,n){
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
DFS1(1,0);DFS2(1,0);
rep(i,1,n)ins(c[i],i);
while(Q--){
scanf("%d",&k);gs[0]=cs1[0]=cs2[0]=ans=0;
while(k--){
scanf("%d",&x);
if(gs[x]){
if(gs[0])ans=max(ans,cal(cs1[0],cs1[x]));
if(gs[0]>1)ans=max(ans,cal(cs2[0],cs1[x]));
}
if(gs[x]>1){
if(gs[0])ans=max(ans,cal(cs1[0],cs2[x]));
if(gs[0]>1)ans=max(ans,cal(cs2[0],cs2[x]));
}
if(gs[x])ins(0,cs1[x]);
if(gs[x]>1)ins(0,cs2[x]);
}
if(!ans)ans=-1;printf("%d\n",ans);
}
return 0;
}