SPOJ 3978 Distance Query tarjan求LCA

题意:给一棵边带权的树

有m个询问x,y 询问x到y的路径上的最长边和最短边

 

思路:离线做

用tarjan求LCA

每次合并时,只把儿子往根上合并 保证并查集的某一节点的祖先也都是这个节点在树上的祖先

并查集每个节点再维护一个与父亲节点的路径上的最长边和最短边

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<vector>
  6 #include<algorithm>
  7 using namespace std;
  8 #define MAXN 100001
  9 struct node
 10 {
 11     int num,weight;
 12     node *next;
 13 };
 14 node *graph[MAXN];
 15 int f[MAXN];
 16 int father[MAXN];
 17 pair<int,int> edge[MAXN];
 18 pair<int,int> a[MAXN];
 19 pair<int,int> ans[MAXN];
 20 vector<pair<int,int> > query[MAXN];
 21 vector<int> b[MAXN];
 22 node memo[2*MAXN];
 23 bool use[MAXN];
 24 int top;
 25 int n,m;
 26 int root;
 27 int x1,x2;
 28 void add(int x,int y,int w)
 29 {
 30     node *p=&memo[top++];
 31     p->num=y; p->next=graph[x]; p->weight=w; graph[x]=p;
 32     p=&memo[top++];
 33     p->num=x; p->next=graph[y]; p->weight=w; graph[y]=p;
 34 }
 35 int find(int x)
 36 {
 37     if(f[x]==-1) return x;
 38     int root=find(f[x]);
 39     edge[x].first=max(edge[x].first,edge[f[x]].first);
 40     edge[x].second=min(edge[x].second,edge[f[x]].second);
 41     f[x]=root;
 42     return root;
 43 }
 44 void merge(int x,int y)
 45 {
 46     if(find(x)!=find(y))
 47     f[find(x)]=find(y);
 48 }
 49 void LCA(int u)
 50 {   
 51     edge[u].first=0; edge[u].second=987654321;
 52     for(node *p=graph[u];p;p=p->next)
 53     if(p->num!=father[u])
 54     {
 55         father[p->num]=u;
 56         LCA(p->num);
 57         edge[p->num].first=edge[p->num].second=p->weight;
 58         merge(p->num,u);
 59     }
 60     use[u]=1;
 61     vector<pair<int,int> >:: iterator i;
 62     int j;
 63     for(i=query[u].begin();i!=query[u].end();i++)
 64         if(use[i->first])
 65             b[find(i->first)].push_back(i->second);
 66     for(j=0;j<b[u].size();j++)
 67     {
 68         find(a[b[u][j]].first); find(a[b[u][j]].second);
 69         ans[b[u][j]]=make_pair(max(edge[a[b[u][j]].first].first,edge[a[b[u][j]].second].first),min(edge[a[b[u][j]].first].second,edge[a[b[u][j]].second].second));
 70     }
 71 
 72 }
 73 int main()
 74 {
 75     memset(graph,0,sizeof(graph));
 76     memset(use,0,sizeof(use));
 77     memset(f,0xff,sizeof(f));
 78     int i;
 79     int x,y,z;
 80     scanf("%d",&n);
 81     top=0;
 82     for(i=1;i<n;i++)
 83     {
 84         scanf("%d%d%d",&x,&y,&z);
 85         add(x,y,z);
 86     }
 87     scanf("%d",&m);
 88     memset(use,0,sizeof(use));
 89     for(i=1;i<=m;i++)
 90     {
 91         scanf("%d%d",&a[i].first,&a[i].second);
 92         query[a[i].first].push_back(make_pair(a[i].second,i));
 93         query[a[i].second].push_back(make_pair(a[i].first,i));
 94     }
 95     father[1]=0;
 96     LCA(1);
 97     for(i=1;i<=m;i++)
 98         printf("%d %d\n",ans[i].second,ans[i].first);
 99     return 0;
100 }
101         
102             
103         

posted on 2012-05-14 21:02  myoi  阅读(505)  评论(0编辑  收藏  举报

导航