【POJ1986】Distance Queries-LCA算法

来源:互联网 发布:淘宝店铺刷单网站 编辑:程序博客网 时间:2024/04/28 14:42

题目:POJ1986

做法:一道LCA算法的模板题,比较简单,就不多说了。

以下是本人代码:

#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;int n,m,a,b,c,d,tot,first[100010],firstq[40010],fa[100010];int lca[40010],f[100010],root[100010];long long dis[100010];char ch;bool vis[100010],visr[100010];struct {int v,d,next;} e[200010];struct {int v,next;} q[80010];void insert(int x,int y,int d){  e[++tot].v=y;  e[tot].d=d;  e[tot].next=first[x];  first[x]=tot;}void insertq(int x,int y,int d){  q[++tot].v=y;  q[tot].next=firstq[x];  firstq[x]=tot;}int find(int x){  int r=x,i=x,j;  while(f[r]!=r) r=f[r];  while(i!=r)  {    j=f[i];f[i]=r;i=j;  }  return r;}void merge(int a,int b){  int x=find(a),y=find(b);  f[x]=y;}int findrt(int x){  int r=x,i=x,j;  while(root[r]!=r) r=root[r];  while(i!=r)  {    j=root[i];root[i]=r;i=j;  }  return r;}void mergert(int a,int b){  int x=findrt(a),y=findrt(b);  root[x]=y;}void tarjan(int v){  f[v]=v;  for(int i=first[v];i>0;i=e[i].next)    if (e[i].v!=fa[v]){  fa[e[i].v]=v;  dis[e[i].v]=dis[v]+e[i].d;  tarjan(e[i].v);}  for(int i=firstq[v];i>0;i=q[i].next)    if (vis[q[i].v]||v==q[i].v) lca[i/2+(i%2)]=find(q[i].v);  vis[v]=1;  merge(v,fa[v]);}int main(){  scanf("%d%d",&n,&m);  dis[1]=fa[1]=tot=0;  for(int i=1;i<=n;i++) root[i]=i;  for(int i=1;i<=m;i++)  {scanf("%d%d%d%c",&a,&b,&d,&ch);while(ch<'A'||ch>'Z') scanf("%c",&ch);insert(a,b,d);insert(b,a,d);int fa=findrt(a),fb=findrt(b);if (fa!=fb) mergert(a,b);  }  tot=0;  scanf("%d",&c);  for(int i=1;i<=c;i++)  {scanf("%d%d",&a,&b);insertq(a,b,i);insertq(b,a,i);  }  for(int i=1;i<=n;i++) f[i]=i;  for(int i=1;i<=n;i++)if (!visr[findrt(i)]) {tarjan(findrt(i));visr[findrt(i)]=1;}  for(int i=1;i<=c;i++)  {a=q[2*i].v,b=q[2*(i-1)+1].v;if (findrt(a)!=findrt(b)) printf("-1\n");else printf("%lld\n",dis[a]+dis[b]-2*dis[lca[i]]);  }    return 0;}


0 0