• poj 1330 LCA问题 (LCA问题转化为RMQ || tarjan算法)


    LCA问题可以与RMQ问题互相转化,长郡中学 郭华阳的《RMQ&LCA问题》讲的很好。

    这个博客也讲的很好:http://dongxicheng.org/structure/lca-rmq/

    Run ID User Problem Result Memory Time Language Code Length Submit Time
    10873609 xinghan0219 1330 Accepted 3176K 47MS G++ 2000B 2012-10-01 19:49:03
    10546730 xinghan0219 1330 Accepted 2032K 63MS G++ 1756B 2012-07-27 17:08:33

    RMQ问题:http://www.cnblogs.com/Missa/archive/2012/10/01/2709686.html

    tarjan算法模版:http://www.cnblogs.com/Missa/archive/2012/10/01/2709749.html

    RMQ+dfs:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 
      6 using namespace std;
      7 
      8 #define MAXN 10005
      9 #define MAXM 105
     10 #define inf 0x7ffffff
     11 int n;
     12 struct Edge
     13 {
     14     int v,next;
     15 }edge[MAXN];
     16 int head[MAXN];
     17 int e;
     18 
     19 void clear()//初始化
     20 {
     21     memset(head,-1,sizeof(head));
     22     e=0;
     23 }
     24 void addEdge(int u,int v)//加边
     25 {
     26     edge[e].v=v;
     27     edge[e].next=head[u];head[u]=e++;
     28 }
     29 int first[MAXN];//结点在搜索顺序数组中最先出现的位置(下标)
     30 int occur[MAXN<<1];//结点在出现的顺序数组重复的也要记录
     31 int depth[MAXN<<1];//结点在搜索树中的深度,与occur相对应
     32 int dp_min[MAXN<<1][20];//dp_min[i][j] 表示从第i个位置开始的2^j个元素中的最小值的下标
     33 int m=0;//不断记录出现的下标
     34 
     35 void dfs(int u,int deep)
     36 {
     37     occur[++m]=u;//进入该点时进行记录
     38     depth[m]=deep;
     39     if(!first[u])
     40         first[u]=m;
     41     for(int i=head[u];i+1;i=edge[i].next)
     42     {
     43         dfs(edge[i].v,deep+1);
     44         occur[++m]=u;//访问子树返回也要标记
     45         depth[m]=deep;
     46     }
     47 }
     48 void init()
     49 {
     50     clear();
     51     m=0;
     52     memset(first,0,sizeof(first));
     53     bool in[MAXN];//记录结点有无入度
     54     memset(in,false,sizeof(in));
     55     int u=0,v=0;
     56     scanf("%d",&n);
     57     for(int i=1;i<n;i++)//注意此题只有n-1条边
     58     {
     59         scanf("%d%d",&u,&v);
     60         addEdge(u,v);//u->v单向
     61         in[v]=true;
     62     }
     63     for(int i=1;i<=n;i++)//从根开始dfs
     64     {
     65         if(!in[i])
     66         {
     67             dfs(i,0);
     68             break;
     69         }
     70     }
     71 }
     72 
     73 void RMQ_init(int num)
     74 {
     75     for(int i=1;i<=num;i++)
     76         dp_min[i][0]=i;//注意dp_min存的不是最小值,而是最小值的下标
     77     for(int j=1;j<20;j++)
     78         for(int i=1;i<=num;i++)
     79         {
     80             if(i+(1<<j)-1 <= num)
     81             {
     82                 dp_min[i][j] = depth[dp_min[i][j-1]] < depth[dp_min[i+(1<<(j-1))][j-1]] ? dp_min[i][j-1] : dp_min[i+(1<<(j-1))][j-1];
     83             }
     84         }
     85 }
     86 
     87 int RMQ_min(int a,int b)
     88 {
     89     int l=first[a],r=first[b];//得到区间左右端点
     90     if(l>r)
     91     {
     92         int t=l;
     93         l=r;
     94         r=t;
     95     }
     96     int k=(int)(log(double(r-l+1))/log(2.0));
     97     int min_id=depth[dp_min[l][k]]<depth[dp_min[r-(1<<k)+1][k]]?dp_min[l][k]:dp_min[r-(1<<k)+1][k];//最小值下标
     98     return occur[min_id];//取得当前下标表示的结点
     99 }
    100 
    101 int main()
    102 {
    103     int t;
    104     int a,b;
    105     scanf("%d",&t);
    106     while(t--)
    107     {
    108         init();
    109         RMQ_init(m);
    110         scanf("%d%d",&a,&b);
    111         printf("%d\n",RMQ_min(a,b));
    112     }
    113     return 0;
    114 }

    tarjan算法:

      1 //O(n+Q)
      2 
      3 #include <iostream>
      4 #include <cstdio>
      5 #include <cstring>
      6 #include <vector>
      7 
      8 using namespace std;
      9 
     10 #define MAXN 10001
     11 
     12 int n,fa[MAXN];
     13 int rank[MAXN];
     14 int indegree[MAXN];
     15 int vis[MAXN];
     16 vector<int> hash[MAXN],Qes[MAXN];
     17 int ances[MAXN];//祖先
     18 
     19 
     20 void init(int n)
     21 {
     22     for(int i=0;i<=n;i++)
     23     {
     24         fa[i]=i;
     25         rank[i]=0;
     26         indegree[i]=0;
     27         vis[i]=0;
     28         ances[i]=0;
     29         hash[i].clear();
     30         Qes[i].clear();
     31     }
     32 }
     33 
     34 int find(int x)
     35 {
     36     if(x != fa[x])
     37         fa[x]=find(fa[x]);
     38     return fa[x];
     39 }
     40 
     41 void unio(int x,int y)
     42 {
     43     int fx=find(x),fy=find(y);
     44     if(fx==fy) return ;
     45     if(rank[fy]<rank[fx])
     46         fa[fy]=fx;
     47     else
     48     {
     49         fa[fx]=fy;
     50         if(rank[fx]==rank[fy])
     51             rank[fy]++;
     52     }
     53 }
     54 
     55 void Tarjan(int u)
     56 {
     57     ances[u]=u;
     58     int i,size = hash[u].size();
     59     for(i=0;i<size;i++)
     60     {
     61         Tarjan(hash[u][i]);//递归处理儿子
     62         unio(u,hash[u][i]);//将儿子父亲合并,合并时会将儿子的父亲改为u
     63         ances[find(u)]=u;//此时find(u)仍为u,即
     64     }
     65     vis[u]=1;
     66     
     67     //查询
     68     size = Qes[u].size();
     69     for(i=0;i<size;i++)
     70     {
     71         if(vis[Qes[u][i]]==1)//即查询的另一个结点开始已经访问过,当前的u在此回合访问。
     72         {
     73             printf("%d\n",ances[find(Qes[u][i])]);//由于递归,此时还是在u
     74             return;
     75         }
     76     }
     77 }
     78 
     79 int main()
     80 {
     81     int t;
     82     int i,j;
     83     scanf("%d",&t);
     84     while(t--)
     85     {
     86         scanf("%d",&n);
     87         init(n);
     88         int s,d;
     89         for(i=1;i<=n-1;i++)
     90         {
     91             scanf("%d%d",&s,&d);
     92             hash[s].push_back(d);
     93             indegree[d]++;
     94         }
     95         scanf("%d%d",&s,&d);
     96         Qes[s].push_back(d);
     97         Qes[d].push_back(s);
     98         for(j=1;j<=n;j++)
     99         {
    100             if(indegree[j]==0)
    101             {
    102                 Tarjan(j);
    103                 break;
    104             }
    105         }
    106     }
    107     return 0;
    108 }
  • 相关阅读:
    8. 使用Java+TestNG+Selenium搭建测试框架做Web UI自动化测试
    7. Selenium的基本使用
    6. Selenium测试工具简介
    4.自动化测试框架及知识体系
    3.当前主流自动化测试工具的对比选型
    2.自动化测试策略
    1.自动化测试概述
    eclipse工程当中的.classpath 和.project文件什么作用?
    Git 命令
    删除指定字符串的算法题,面试时候没做出来
  • 原文地址:https://www.cnblogs.com/Missa/p/2709889.html
Copyright © 2020-2023  润新知