Factory
题目链接:Factory
思路:在线LCA算法+暴力枚举两个子公司的所有点对
代码:
#include<stdio.h>
#include<math.h>
#include<set>
#include<string.h>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e5+10;
set<int>p[maxn];
struct edge
{
int v,w,next,flag;
} E[maxn<<1];
int first[maxn],val[maxn],dep[maxn],a[maxn<<1],b[maxn],f[maxn<<1][20],lca[maxn<<1][20];
int top,len,n,m;
set<int>::iterator it1,it2;
void dfs(int x,int step,int va)
{
dep[x]=step;
a[++top]=x,val[x]=va;
for(int i=first[x]; ~i; i=E[i].next)
{
if(E[i].flag)
continue;
E[i].flag=E[i^1].flag=1;
int v=E[i].v,w=E[i].w;
dfs(v,step+1,va+w);
a[++top]=x;
}
}
void init()
{
for(int i=1; i<=top; ++i)
{
f[i][0]=dep[a[i]];
lca[i][0]=a[i];
}
int s=(int)log2(top*1.0);
for(int j=1; j<=s; ++j)
{
int k=top-(1<<j)+1;
for(int i=1; i<=k; ++i)
{
int x=i+(1<<(j-1));
if(f[i][j-1]<=f[x][j-1])
{
f[i][j]=f[i][j-1];
lca[i][j]=lca[i][j-1];
}
else
{
f[i][j]=f[x][j-1];
lca[i][j]=lca[x][j-1];
}
}
}
}
void add_edge(int u,int v,int w)
{
E[len].v=v,E[len].w=w,E[len].flag=0,E[len].next=first[u],first[u]=len++;
}
int main()
{
int t,Q;
scanf("%d",&t);
while(t--)
{
memset(b,0,sizeof(b));
memset(first,-1,sizeof(first));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
p[i].clear();
len=0,top=0;
int u,v,w;
for(int i=1; i<n; ++i)
{
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
add_edge(v,u,w);
}
dfs(1,1,0);
for(int i=1; i<=top; ++i)
if(b[a[i]]==0)
b[a[i]]=i;
init();
for(int i=1; i<=m; ++i)
{
scanf("%d",&w);
for(int j=0; j<w; ++j)
{
scanf("%d",&u);
p[i].insert(u);
}
}
scanf("%d",&Q);
while(Q--)
{
scanf("%d%d",&u,&v);
int ans=inf;
for(it1=p[u].begin(); it1!=p[u].end(); ++it1)
for(it2=p[v].begin(); it2!=p[v].end(); ++it2)
{
int x=*it1,y=*it2;
x=b[x],y=b[y];
if(x>y)
swap(x,y);
int j=(int)log2((y-x)*1.0);
int i=y-(1<<j)+1;
int fa=f[x][j]<f[i][j]?lca[x][j]:lca[i][j];
ans=min(ans,val[a[x]]+val[a[y]]-2*val[fa]);
}
printf("%d\n",ans);
}
}
return 0;
}