中文题,题意不说了。这题应该是数据弱,直接大力LCA就行。。。用lca求出两个集合中距离最小的两个点的距离,就是答案。
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int inf = 1e9;
struct edge
{
int to,cost;
edge(int _to,int _cost)
{
to = _to;
cost = _cost;
}
};
vector<edge> e[100010];
int n,m;
int fa[100010][20];
int deep[100010];
int dis[100010];
void dfs(int x,int pre,int d,int len)
{
fa[x][0] = pre;
deep[x] = d;
dis[x] = len;
for(int i=0;i<e[x].size();i++)
{
int xx = e[x][i].to;
if(xx == pre)
continue;
dfs(xx,x,d+1,len+e[x][i].cost);
}
}
void init()
{
memset(deep,-1,sizeof(deep));
memset(dis,-1,sizeof(dis));
dfs(1,0,0,0);
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i<=n;i++)
{
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
int lca(int a,int b)
{
if(deep[a]>deep[b])
swap(a,b);
int f=deep[b]-deep[a];
for(int i=0;(1<<i)<=f;i++)
{
if((1<<i)&f)
b=fa[b][i];
}
if(a!=b)
{
for(int i=(int)log2(n);i>=0;i--)
{
if(fa[a][i]!=fa[b][i])
{
a=fa[a][i];
b=fa[b][i];
}
}
a=fa[a][0];
}
return a;
}
int dist(int a,int b)
{
int k = lca(a,b);
return dis[a] + dis[b] - 2*dis[k];
}
vector<int> v[100010];
int main(void)
{
int T,i,j;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
e[i].clear();
for(i=1;i<=m;i++)
v[i].clear();
for(i=1;i<n;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
e[x].push_back(edge(y,z));
e[y].push_back(edge(x,z));
}
for(i=1;i<=m;i++)
{
int k;
int x;
scanf("%d",&k);
for(j=0;j<k;j++)
{
scanf("%d",&x);
v[i].push_back(x);
}
}
init();
int q;
scanf("%d",&q);
while(q--)
{
int a,b;
scanf("%d%d",&a,&b);
int minn = inf;
for(i=0;i<v[a].size();i++)
for(j=0;j<v[b].size();j++)
{
minn = min(minn,dist(v[a][i],v[b][j]));
}
printf("%d\n",minn);
}
}
return 0;
}
340

被折叠的 条评论
为什么被折叠?



