GCPC
详细题解
A. Attack on Alpha-Zet(lca)
题意:
问按序号从小到大走完全程需要走多少格,保证两点之间只有一条路
思路: 转化建树,因为题目保证任何两点之间只有一条路,lca即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1005;
char mp[N][N*2];
int n,m;
int head[N*N],cnt;
struct node
{
int v,nxt;
}edge[N*N*2];
int id(int x,int y)
{
return (x-1)*m+(y+1)/2;
}
void add(int u,int v)
{
edge[cnt].v=v;
edge[cnt].nxt=head[u];
head[u]=cnt++;
}
int grand[N*N][22]={
0};
int depth[N*N],DEPTH,sum=1;
void dfs(int x)
{
for(int i=1;i<=DEPTH;i++)
{
grand[x][i]=grand[grand[x][i-1]][i-1];
}
for(int i=head[x];i!=-1;i=edge[i].nxt)
{
int to=edge[i].v;
if(grand[x][0]==to)continue;
depth[to]=depth[x]+1;
grand[to][0]=x;
dfs(to);
}
}
void init(int s)
{
DEPTH=floor(log(n*m + 0.0) / log(2.0));
depth[s]=1;
memset(grand,0,sizeof(grand));
dfs(s);
}
int lca(int a,int b)
{
if(depth[a]>depth[b])swap(a,b);
for(int i=DEPTH;i>=0;i--)
if(depth[a]<depth[b]&&depth[grand[b][i]]>=depth[a])
b=grand[b][i];
for(int i=DEPTH;i>=0;i--)
if(grand[a][i]!=grand[b][i])
{
a=grand[a][i];
b=grand[b][i];
}
if(a!=b)
{
return grand[a][0];
}
return a;
}
int main()
{
scanf("%d%d",&n,&m);
getchar();
memset(head,-1,sizeof head);
for(int i=0;i<=n;i++)
{
gets(mp[i]);
}
for(int i=1;i<=n;i++