首页 > 代码库 > BZOJ 1602: [Usaco2008 Oct]牧场行走

BZOJ 1602: [Usaco2008 Oct]牧场行走

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1602

解:lca的模板,我用的是倍增。

程序:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
struct ding{
  int to,next,val;
}edge[2010];
int n,q,f[1010][11],dep[1010],cnt,head[1010],sum[1010];
bool vis[1010];
inline int read()
{
  int ef=0; char ch;
  while ((ch<0)||(ch>9)) ch=getchar();
  while ((ch>=0)&&(ch<=9)) 
  {
      ef=ef*10+ch-0;
    ch=getchar();
  }
  return ef;
}
void add(int u,int v,int w)
{
  edge[++cnt].to=v; edge[cnt].val=w; edge[cnt].next=head[u]; head[u]=cnt;
}
void dfs(int x,int d)
{
  vis[x]=true;
  dep[x]=d;
  for (int i=1;i<=10;i++) f[x][i]=f[f[x][i-1]][i-1];
  for (int i=head[x];i;i=edge[i].next)
  {
      int y=edge[i].to;
      if (!vis[y])
      {
        f[y][0]=x; sum[y]+=sum[x]+edge[i].val;dfs(y,d+1);    
    }
  }
}
int lca(int u,int v)
{
  if (dep[u]>dep[v]) return (lca(v,u));
  int x=dep[v]-dep[u];
  for (int i=10;i>=0;i--) if (x&(1<<i)) v=f[v][i];
  if (u==v) return u;
  for (int i=10;i>=0;i--)
  if (f[u][i]!=f[v][i])
  {
      u=f[u][i]; v=f[v][i];
  }
  return f[u][0];
}
int main()
{
  n=read(); q=read();
  int x,y,w;
  for (int i=1;i<n;i++)
  {
      x=read(); y=read(); w=read();
      add(x,y,w); add(y,x,w);
  }
  f[1][0]=1;
  dfs(1,1);
  for (int i=1;i<=q;i++)
  {
      x=read(); y=read();
      printf("%d\n",sum[x]+sum[y]-2*sum[lca(x,y)]);
  }
  return 0;
}

 

BZOJ 1602: [Usaco2008 Oct]牧场行走