题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6115
题意:中文题面
分析:直接维护LCA,然后暴力枚举集合维护答案即可。
#include <bits/stdc++.h> using namespace std; const int maxn = 200010; const int inf = 0x3f3f3f3f; struct edge{ int to,len,next; }E[maxn*2]; vector<int>G[maxn]; int head[maxn],edgecnt,fa[maxn][20],dis[maxn],dep[maxn]; void init(){ edgecnt=0; memset(head,-1,sizeof(head)); } void add(int u, int v, int w){ E[edgecnt].to=v,E[edgecnt].len=w,E[edgecnt].next=head[u],head[u]=edgecnt++; } void dfs(int x,int d,int Len, int pre){ dis[x]=Len; dep[x] = d; fa[x][0]=pre; for(int i=1; i<20; i++){ fa[x][i]=fa[fa[x][i-1]][i-1]; } for(int i=head[x];~i;i=E[i].next){ int v=E[i].to; if(v == pre) continue; int len=E[i].len; if(v==pre) continue; dfs(v, d+1, Len + len, x); } } int LCA(int u, int v){ if(dep[u]<dep[v]) swap(u,v); for(int i=19; i>=0; i--){ if(dep[fa[u][i]]>=dep[v]){ u=fa[u][i]; } } if(u==v) return u; for(int i=19; i>=0; i--){ if(fa[u][i]!=fa[v][i]){ u=fa[u][i]; v=fa[v][i]; } } return fa[u][0]; } int n, m; int getLen(int u, int v){ int _lca = LCA(u,v); return dis[u]+dis[v]-2*dis[_lca]; } int main() { int T; scanf("%d", &T); while(T--) { for(int i=0; i<maxn; i++) G[i].clear(); memset(dis, 0, sizeof(dis)); memset(fa, 0, sizeof(fa)); scanf("%d%d",&n,&m); init(); for(int i=1; i<n; i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } dfs(1,0,0,-1); for(int i=1; i<=m; i++){ int num,x; scanf("%d", &num); while(num--){ scanf("%d",&x); G[i].push_back(x); } } int q; scanf("%d", &q); while(q--) { int a,b; scanf("%d%d",&a,&b); int ans = 0x3f3f3f3f; for(int i=0; i<G[a].size(); i++){ for(int j=0; j<G[b].size(); j++){ ans = min(ans, getLen(G[a][i], G[b][j])); } } printf("%d ", ans); } } return 0; }