模板最近的共同祖先

LCA tarjan 离线算法

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 40010;
int first[maxn], head[maxn], cnt, sum;
struct edge
{
	int u, v, w, next;
}e[maxn*2], qe[maxn], Q[maxn];
int ans[maxn];
int f[maxn], vis[maxn];
int d[maxn];
void AddEdge(int u, int v, int w)
{
	e[cnt].u = u;
	e[cnt].v = v;
	e[cnt].w = w;
	e[cnt].next = first[u];
	first[u] = cnt++;
	e[cnt].u = v;
	e[cnt].v = u;
	e[cnt].w = w;
	e[cnt].next = first[v];
	first[v] = cnt++;
}

int find(int x)
{
	if(f[x] != x)
		return f[x] = find(f[x]);
	return f[x];
}
void LCA(int u, int k)
{
	f[u] = u;
	d[u] = k;
	vis[u] = true;
	for(int i = first[u]; i != -1; i = e[i].next)
	{
		int v = e[i].v;
		if(vis[v])
			continue;	
		LCA(v, k + e[i].w);
		f[v] = u;
	}
	for(int i = head[u]; i != -1; i = qe[i].next)
	{
		int v = qe[i].v;
		if(vis[v])
		{
			ans[qe[i].w] = find(v);
		}
	}
} 

LCA 转RMQ的在线算法

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 200010;
struct edge
{
	int u, v, w, next;
}edges[maxn*2], e[maxn];

int E[maxn*2], H[maxn*2], I[maxn*2], L[maxn], R[maxn];
int dp[maxn*2][40];
int cnt, clock, dfn;
int first[maxn];
int a[maxn<<2];
int b[maxn];
int add[maxn<<2];
int degree[maxn];
int vis[maxn];
void AddEdge(int u, int v, int w)
{
	edges[cnt].u = u;
	edges[cnt].v = v;
	edges[cnt].w = w;
	edges[cnt].next = first[u];
	first[u] = cnt++;
	edges[cnt].u = v;
	edges[cnt].v = u;
	edges[cnt].w = w;
	edges[cnt].next = first[v];
	first[v] = cnt++;	
}
void dfs(int u, int fa, int dep)
{
	E[++clock] = u;
	H[clock] = dep;
	I[u] = clock;
	L[u] = ++dfn;
	b[dfn] = u;
	for(int i = first[u]; i != -1; i = edges[i].next)
	{
		int v = edges[i].v;
		if(v == fa)
			continue;
		if(vis[v])
			continue;
		vis[v] = true;
		dfs(v, u, dep+1);
		E[++clock] = u;
		H[clock] = dep;
	}
	R[u] = dfn;
}

void RMQ_init(int n)
{
	for(int i = 1; i <= n; i++)
		dp[i][0] = i;
	for(int j = 1; (1<<j) <= n; j++)
		for(int i = 1; i+(1<<j)-1 <= n; i++)
		{
			if(H[dp[i][j-1]] < H[dp[i+(1<<(j-1))][j-1]])
				dp[i][j] = dp[i][j-1];
			else
				dp[i][j] = dp[i+(1<<(j-1))][j-1];
		}
}
int RMQ(int l, int r)
{
	l = I[l], r = I[r];
	if(l > r)
		swap(l, r);
	int len = r-l+1, k = 0;
	while((1<<k) <= len)
		k++;
	k--;
	if(H[dp[l][k]] < H[dp[r-(1<<k)+1][k]])
		return E[dp[l][k]];
	else
		return E[dp[r-(1<<k)+1][k]];
}


LCA倍增法

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 20010;
const int INF = 999999999;
int anc[maxn][16], maxcost[maxn][16];
int fa[maxn], L[maxn], cost[maxn], vis[maxn];
int n, m;
int first[maxn], cnt;
struct edge
{
	int u, v, next;
}e[maxn*2];

void AddEdge(int u, int v)
{
	e[cnt].v = v;
	e[cnt].next = first[u];
	first[u] = cnt++;
	e[cnt].v = u;
	e[cnt].next = first[v];
	first[v] = cnt++;
}

void pre()
{
	for(int i = 1; i <= n; i++)
	{
		anc[i][0] = fa[i]; maxcost[i][0] = cost[i];
		for(int j = 1; (1<<j) < n; j++)
			anc[i][j] = -1;
	}
	for(int j = 1; (1<<j) < n; j++)
		for(int i = 1; i <= n; i++)
			if(anc[i][j-1] != -1)
			{
				int a = anc[i][j-1];
				anc[i][j] = anc[a][j-1];
				maxcost[i][j] = max(maxcost[i][j-1], maxcost[a][j-1]);
			}
	
}

int query(int p, int q)
{
	int tmp, log, i;
	if(L[p] < L[q])
		swap(p, q);
	for(log = 1; (1<<log) <= L[p]; log++);
	log--;
	
	int ans = -INF;
	for(int i = log; i >= 0; i--)
		if(L[p] - (1<<i) >= L[q])
		{
			ans = max(ans, maxcost[p][i]);
			p = anc[p][i];
		}
	if(p == q)
		return ans;
	for(int i = log; i >= 0; i--)
	{
		if(anc[p][i] != -1 && anc[p][i] != anc[q][i])
		{
			ans = max(ans, maxcost[p][i]);
			ans = max(ans, maxcost[q][i]);
			p = anc[p][i];
			q = anc[q][i];
		}
	}
	ans = max(ans, cost[p]);
	ans = max(ans, cost[q]);
	return ans;
}
void dfs(int u)
{
	for(int i = first[u]; i != -1; i = e2[i].next)
	{
		int v = e[i].v;
		if(vis[v])
			continue;
		vis[v] = 1;
		fa[v] = u;
		L[v] = L[u]+1;
		dfs(v);
	}
}


 

版权声明:本文博主原创文章。博客,未经同意不得转载。

posted @ 2015-09-28 14:51  lcchuguo  阅读(172)  评论(0编辑  收藏  举报