• 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         
  • 相关阅读:
    二叉树的构造与遍历
    最长公共子序列
    Python爬虫与数据图表的实现
    降维实例之主成分分析
    数据集之转换器以及估计器
    机器学习算法分类以及开发流程
    数据的降维之特征选择及主成分分析
    特征工程之归一化及标准化
    文本tfidf
    文本特征抽取
  • 原文地址:https://www.cnblogs.com/myoi/p/2500371.html
Copyright © 2020-2023  润新知