原理讲解:http://dongxicheng.org/structure/lca-rmq/
在线算法模板:
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
#include
#include
#include
#include
using namespace std;
const int INF=0x3f3f3f;
const int maxn=111111;
const int maxm=111111;
int n,m;
struct EDGENODE{
int to;
int w;
int next;
};
struct SGRAPH{
int head[maxn];
EDGENODE edges[maxm];
int edge;
void init(){
memset(head,-1,sizeof(head));
edge=0;
}
void addedge(int u,int v,int c){
edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++;
}
//------------
int d[maxn][20];
//元素从1编号到n
void makeRmqIndex(int A[],int n){
for(int i=1;i<=n;i++) d[i][0]=i;
for(int j=1;(1<=R[v]) return E[rmqIndex(R[v],R[u],D)];
else return E[rmqIndex(R[u],R[v],D)];
}
//--------------------
int deep[maxn];
void getd(int u,int p,int w){
deep[u]=w;
for (int i=head[u];i!=-1;i=edges[i].next){
int v=edges[i].to;
if (v==p) continue;
getd(v,u,w+edges[i].w);
}
}
int getDis(int u,int v){
int lca=LCA(u,v);
return deep[u]+deep[v]-deep[lca]*2;
}
int done(int x,int y,int z){
int ans=INF,res=0;
int lca1,lca2;
lca1=LCA(x,y);
res=deep[x]+deep[y]-deep[lca1]*2;
lca2=LCA(lca1,z);
res+=deep[lca1]+deep[z]-deep[lca2]*2;
ans=min(ans,res);
lca1=LCA(x,z);
res=deep[x]+deep[z]-deep[lca1]*2;
lca2=LCA(lca1,y);
res+=deep[lca1]+deep[y]-deep[lca2]*2;
ans=min(ans,res);
lca1=LCA(y,z);
res=deep[y]+deep[z]-deep[lca1]*2;
lca2=LCA(lca1,x);
res+=deep[lca1]+deep[x]-deep[lca2]*2;
ans=min(ans,res);
return ans;
}
}solver;
/**
LCA(离线算法)
主函数除建边外还应调用
init();
dir[1]=0;
tarjan(1);
*/
#include
#include
#include
#include
using namespace std;
const int maxn=40010;
struct note
{
int u,v,w,lca,next;
}edge[maxn*2],edge1[805];
int head[maxn],ip,head1[maxn],ip1;///需要建两次边。1,该树的边2,需要查询的两点
int m,n;
int father[maxn],vis[maxn],dir[maxn];
///依次表示u点的祖先、标记是否访问过,到根节点的距离
void init()
{
memset(vis,0,sizeof(vis));
memset(dir,0,sizeof(dir));
memset(head,-1,sizeof(head));
memset(head1,-1,sizeof(head1));
ip=ip1=0;
}
void addedge(int u,int v,int w)
{
edge[ip].v=v,edge[ip].w=w,edge[ip].next=head[u],head[u]=ip++;
}
void addedge1(int u,int v)
{
edge1[ip1].u=u,edge1[ip1].v=v,edge1[ip1].lca=-1,edge1[ip1].next=head1[u],head1[u]=ip1++;
}
int Find(int x)
{
if(father[x]==x)
return x;
return father[x]=Find(father[x]);
}
void Union(int x,int y)
{
x=Find(x);
y=Find(y);
if(x!=y)
father[y]=x;
}
void tarjan(int u)
{
vis[u]=1;
father[u]=u;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
int w=edge[i].w;
if(!vis[v])
{
dir[v]=dir[u]+w;
tarjan(v);
Union(u,v);
}
}
for(int i=head1[u];i!=-1;i=edge1[i].next)
{
int v=edge1[i].v;
if(vis[v])
{
edge1[i].lca=edge1[i^1].lca=father[Find(v)];
}
}
}