题目:http://poj.org/problem?id=1330
讲解:http://blog.csdn.net/tingyun_say/article/details/52092464
离线算法:dfs+并查集(Tarjan)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
using namespace std;
const int N=1e4+107;
const int inf=0x3f3f3f3f;
int n,q1,q2;
int f[N],a[N];
bool c[N],flag[N];
vector<int> v[N];
int find(int k)
{
if(f[k]==k) return k;
f[k]=find(f[k]);
return f[k];
}
int unions(int x,int y)
{
int xx=find(x),yy=find(y);
f[yy]=xx;
return 0;
}
int tarjan(int u)
{
for(int i=0;i<v[u].size();i++)
{
tarjan(v[u][i]);
unions(u,v[u][i]);
a[find(u)]=u;
}
c[u]=1;
if(q1==u&&c[q2]) printf("%d\n",a[find(q2)]);
else if(q2==u&&c[q1]) printf("%d\n",a[find(q1)]);
return 0;
}
int main()
{
int t,i;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
{
v[i].clear();
f[i]=i;
a[i]=0;
c[i]=0;
flag[i]=1;
}
for(i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
flag[y]=0;
v[x].push_back(y);
}
scanf("%d%d",&q1,&q2);
for(i=1;i<=n;i++) if(flag[i]) break;
tarjan(i);
}
return 0;
}
在线算法:dfs+RMQ(RMQ)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
using namespace std;
const int N=1e4+107;
const int inf=0x3f3f3f3f;
const int log=20;
int dp[N][log],depth[N],deg[N];
struct node{
int to;
node *next;
}g[2*N],*cur,*head[N];
void addnode(int u,int v)
{
cur->to=v;
cur->next=head[u];
head[u]=cur++;
}
void dfs(int u)
{
depth[u]=depth[dp[u][0]]+1;
for(int i=1;i<log;i++) dp[u][i]=dp[dp[u][i-1]][i-1];
for(node *it=head[u];it;it=it->next) dfs(it->to);
}
int lca(int u,int v)
{
if(depth[u]<depth[v]) swap(u,v);
for(int st=1<<(log-1),i=log-1; i>=0 ;i--,st>>=1)
if(st<=depth[u]-depth[v]) u=dp[u][i];
if(u==v) return u;
for(int i=log-1;i>=0;i--)
if(dp[v][i]!=dp[u][i])
v=dp[v][i],u=dp[u][i];
return dp[u][0];
}
void init(int n)
{
for(int i=0;i<=n;i++)
{
dp[i][0]=0;
head[i]=NULL;
deg[i]=0;
}
cur=g;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,u,v;
scanf("%d",&n);
init(n);
for(int i=0;i<n-1;i++)
{
scanf("%d%d",&u,&v);
addnode(u,v);
deg[v]++;
dp[v][0]=u;
}
for(int i=1;i<=n;i++)
if(deg[i]==0){dfs(i);break;}
scanf("%d%d",&u,&v);
printf("%d\n",lca(u,v));
}
}
HDU 2586
Lca
#define N 50005
vector<int> mp[N],w[N],query[N],num[N];
int p[N],d[N],res[N];
bool vis[N];
int n;
void Init()
{
int i;
for(i=1;i<=n;i++)
{
mp[i].clear();
w[i].clear();
query[i].clear();
num[i].clear();
p[i]=i;
d[i]=0;
vis[i]=false;
}
}
int Find(int x)
{
if(p[x]!=x)
p[x]=Find(p[x]);
return p[x];
}
void Union(int x,int y)
{
x=Find(x);
y=Find(y);
if(x!=y)
p[y]=x;
}
void Tarjan(int cur,int v)
{
int size,i,tmp;
vis[cur]=true;
d[cur]=v;
size=mp[cur].size();
for(i=0;i<size;i++)
{
tmp=mp[cur][i];
if(vis[tmp]) continue;
Tarjan(tmp,v+w[cur][i]);
Union(cur,tmp);
}
size=query[cur].size();
for(i=0;i<size;i++)
{
tmp=query[cur][i];
if(!vis[tmp])continue;
res[num[cur][i]]=d[cur]+d[tmp]-2*d[Find(tmp)];
}
}
int main()
{
int T,q,a,b,c,i;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&q);
Init();
for(i=1;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
mp[a].push_back(b);
w[a].push_back(c);
mp[b].push_back(a);
w[b].push_back(c);
}
for(i=0;i<q;i++)
{
scanf("%d%d",&a,&b);
query[a].push_back(b);
query[b].push_back(a);
num[a].push_back(i);
num[b].push_back(i);
}
Tarjan(1,0);
for(i=0;i<q;i++)
printf("%d\n",res[i]);
}
return 0;
}