hdu 6115 Factory (LCA在线+暴力 水过)

我们将A省简化为由N个城市组成,某些城市之间存在双向道路,而且A省的交通有一个特点就是任意两个城市之间都能通过道路相互到达,且在不重复经过城市的情况下任意两个城市之间的到达方案都是唯一的。聪明的你一定已经发现,这些城市构成了树这样一个结构。

现在百度陆续开了许许多多的子公司。每家子公司又会在各城市中不断兴建属于该子公司的办公室。

由于各个子公司之间经常有资源的流动,所以公司员工常常想知道,两家子公司间的最小距离。
我们可以把子公司看成一个由办公室组成的集合。那么两个子公司A和B的最小距离定义为min(dist(x,y))(x∈A,y∈B)。其中dist(x,y)表示两个办公室之间的最短路径长度。

现在共有Q个询问,每次询问分别在两个子公司间的最小距离。

Input

第一行一个正整数T,表示数据组数。

对于每组数据:

第一行两个正整数N和M。城市编号为1至N,子公司编号为1至M。

接下来N-1行给定所有道路的两端城市编号和道路长度。

接下来M行,依次按编号顺序给出各子公司办公室所在位置,每行第一个整数G,表示办公室数,接下来G个数为办公室所在位置。

接下来一个整数Q,表示询问数。

接下来Q行,每行两个正整数a,b(a不等于b),表示询问的两个子公司。


【数据范围】

0<=边权<=100

1<=N,M,Q,工厂总数<=100000

Output

对于每个询问,输出一行,表示答案。

Sample Input

1
3 3
1 2 1
2 3 1
2 1 1
2 2 3
2 1 3
3
1 2
2 3
1 3

Sample Output

1
0
0

思路:LCA+暴力,这题估计是数据水了。正解好像是虚树,不过我没学过。

           先找出LCA,遍历一遍工作室,找最小的

#include<bits/stdc++.h>
#define M 100010
using namespace std;
struct path
{
    int to,nextt,w;
}A[2*M];
vector<int>q[2*M];
int t,n,m,x,y,w,tot,carry,lca;
int head[M],vis[M],first[M],ver[2*M],d[M],num[2*M],dp[2*M][20];
void init()
{
    for(int i=1;i<=m;i++)
        q[i].clear();
    tot=carry=0;
    memset(vis,0,sizeof(vis));
    memset(head,-1,sizeof(head));
}
void add(int u,int v,int w)
{
    A[tot].to=v;
    A[tot].w=w;
    A[tot].nextt=head[u];
    head[u]=tot++;
}
void dfs(int u,int dep)
{
    int tem;
    vis[u]=1;
    first[u]=++carry;
    num[carry]=dep;
    ver[carry]=u;
    for(int i=head[u]; i!=-1; i=A[i].nextt)
    {
        tem=A[i].to;
        if(vis[tem]==0)
        {
            d[tem]=d[u]+A[i].w;
            dfs(tem,dep+1);
            num[++carry]=dep;
            ver[carry]=u;
        }
    }
}
void ST()
{
    int k=log2((double)(carry));
    for(int i=1;i<=carry;i++) dp[i][0]=i;
    for(int j=1;j<=k;j++)
    {
        for(int i=1;i+(1<<j)<=carry;i++)
        {
            int a=dp[i][j-1],b=dp[i+(1<<(j-1))][j-1];
            dp[i][j]=num[a]<num[b]?a:b;
        }
    }
}
int RMQ(int x,int y)
{
    x=first[x];
    y=first[y];
    if(x>y) swap(x,y);
    int k=log2((double)(y-x+1));
    int a=dp[x][k],b=dp[y-(1<<k)+1][k];
    return num[a]<num[b]?ver[a]:ver[b];
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        init();
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&x,&y,&w);
            add(x,y,w);
            add(y,x,w);
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&x);
            while(x--)
            {
                scanf("%d",&y);
                q[i].push_back(y);
            }
        }
        dfs(1,1);
        ST();
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d",&x,&y);
            int ans=1e9,u,v;
            int lenx=q[x].size(),leny=q[y].size();
            for(int i=0;i<lenx;i++)
            {
                for(int j=0;j<leny;j++)
                {
                    u=q[x][i],v=q[y][j];
                    lca=RMQ(u,v);
                    ans=min(ans,d[u]+d[v]-2*d[lca]);
                }
            }
            printf("%d\n",ans);
        }
    }
}

          

猜你喜欢

转载自blog.csdn.net/weixin_41380961/article/details/84666697