第十三届蓝桥杯大赛软件赛决赛C/C++大学B组 H: 机房

P8805 [蓝桥杯 2022 国 B] 机房

H: 机房 —— 参考地址

终于算是拿下国赛LCA模板题了
第十三届蓝桥杯大赛软件赛决赛C/C++大学B组 H: 机房_第1张图片

思路:给你一个树,求任意两点之间的所有点——直接连接点的数量和,可以说是用LCA。
预处理从根节点到子节点的度数之和,然后利用LCA,计算出它们的公共祖先,减去2倍的根节点到公共祖先的度数和,最后在加上公共祖先本身的度数。
#include
using namespace std;

const int N = 100010;
int f[N][18],d[N],dist[N];
int sz[N];
vector<int> g[N];

void bfs()
{
	queue<int> q;
	q.push(1);
	d[1]=1;
	dist[1]=sz[1];
	
	while(!q.empty())
	{
		int u=q.front();q.pop();
		for(auto &p:g[u])
		{
			int j=p;
			if(d[j]) continue;
			d[j]=d[u]+1;
			dist[j]=dist[u]+sz[j];
			f[j][0]=u;
			for(int k=1;k<=16;k++)
				f[j][k]=f[f[j][k-1]][k-1];
			q.push(j);
		}
	}
}

int lca(int x,int y)
{
	if(d[x]>d[y]) swap(x,y);
	for(int i=15;i>=0;i--)
		if(d[f[y][i]]>=d[x])
			y=f[y][i];
	if(x==y) return x;
	for(int i=15;i>=0;i--)
		if(f[x][i]!=f[y][i])
			x=f[x][i],y=f[y][i];
	return f[x][0]; 
}

int main()
{
	int n,m;cin>>n>>m;
	for(int i=1;i<=n;i++) g[i].clear();
	for(int i=1;i<=n-1;i++)
	{
		int a,b,c;cin>>a>>b;
		g[a].push_back(b);
		g[b].push_back(a);
		sz[a]++,sz[b]++;
	}
	bfs();
	for(int i=1;i<=m;i++)
	{
		int x,y;cin>>x>>y;
		int pos=lca(x,y);
		cout<<dist[x]+dist[y]-2*dist[pos]+sz[pos]<<endl;
	}
	return 0;
}
#include
using namespace std;

const int N = 100010, M = N << 1;

int h[N],e[M],w[M],ne[M],idx;
int f[N][18],d[N],dist[N];
int sz[N];

void add(int a,int b,int c)
{
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}

void bfs()
{
    queue<int> Q;
    Q.push(1);
    d[1]=1;
    dist[1]=sz[1];
    
    while(!Q.empty())
    {
        int t=Q.front();Q.pop();
        for(int i=h[t];~i;i=ne[i])
        {
            int j=e[i];
            if(d[j]) continue;
            d[j]=d[t]+1;
            dist[j]=dist[t]+sz[j];
            f[j][0]=t;
            for(int k=1;k<=15;k++)
                f[j][k]=f[f[j][k-1]][k-1];
            Q.push(j);
        }
    }
}

int lca(int x,int y)
{
    if(d[x]>d[y]) swap(x,y);
    for(int i=15;i>=0;i--)
        if(d[f[y][i]]>=d[x])
            y=f[y][i];
    if(x==y) return x;
    for(int i=15;i>=0;i--)
        if(f[x][i]!=f[y][i])
            x=f[x][i],y=f[y][i];
    return f[x][0];
}

int main()
{
    memset(h,-1,sizeof h);
    memset(f,0,sizeof f);
    memset(d,0,sizeof d);
    memset(dist,0,sizeof dist);
    
    int n,m;cin>>n>>m;
    for(int i=1;i<=n-1;i++)
    {
        int a,b,c;cin>>a>>b;
        add(a,b,1),add(b,a,1);
        sz[a]++,sz[b]++;
    }
    bfs();
    for(int i=1;i<=m;i++)
    {
        int x,y;cin>>x>>y;
        int pos=lca(x,y);
        cout<<dist[x]+dist[y]-dist[pos]*2+sz[pos]<<endl;
    }
    return 0;
}

你可能感兴趣的:(#,图论,#,蓝桥杯,c++,蓝桥杯,c语言)