HDU 5044 离线LCA算法

昨天写了HDU 3966 ,本来这道题是很好解得,结果我想用离线LCA 耍一把,结果发现离线LCA 没理解透,错了好多遍,终得AC ,这题比起 HDU 3966要简单,因为他不用动态查询。但是我还是错了好多遍  T^T。。。

http://acm.split.hdu.edu.cn/showproblem.php?pid=5044

不多说了  思想不是很清楚的可以看一看我的上一篇博文 HDU 3966

直接贴代码

  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include <string>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <map>
  8 #include <set>
  9 #include <queue>
 10 #include <stack>
 11 #include<stdlib.h>
 12 #include <vector>
 13 using namespace std;
 14 #pragma comment(linker, "/STACK:1024000000,1024000000")
 15 #define ll __int64
 16 #define CL(a,b) memset(a,b,sizeof(a))
 17 #define MAXNODE 100010
 18
 19 int n,q;
 20
 21 typedef struct myedge
 22 {
 23     int v,next,p;
 24 }E;
 25
 26 E edge[MAXNODE*2];
 27 int head[MAXNODE],ce;
 28
 29 void inithead()
 30 {
 31     CL(head,-1);
 32     ce=0;
 33 }
 34 void addedge(int s,int e,int p)
 35 {
 36     edge[ce].p=p;edge[ce].v=e;edge[ce].next=head[s];head[s]=ce++;
 37     edge[ce].p=p;edge[ce].v=s;edge[ce].next=head[e];head[e]=ce++;
 38 }
 39
 40 typedef struct opedge
 41 {
 42     int v,t,k,p,next;
 43 }O;
 44
 45 O op[MAXNODE*2];
 46 int heado[MAXNODE],co;
 47 int etn[MAXNODE];
 48
 49 void initheado()
 50 {
 51     CL(heado,-1);
 52     CL(etn,0);
 53     co=0;
 54 }
 55
 56 void addo(int s,int e,int t,int k,int p)
 57 {
 58     op[co].t=t;op[co].v=e;op[co].next=heado[s];op[co].p=p;op[co].k=k;heado[s]=co++;
 59     op[co].t=t;op[co].v=s;op[co].next=heado[e];op[co].p=p;op[co].k=k;heado[e]=co++;
 60 }
 61
 62 int fa[MAXNODE];
 63 int fifa(int i)
 64 {
 65     if(fa[i]==i)return i;
 66     fa[i]=fifa(fa[i]);
 67     return fa[i];
 68 }
 69
 70 int pre[MAXNODE];
 71 int tagp[MAXNODE];
 72 ll  re[MAXNODE][2];
 73 int tag[MAXNODE];
 74
 75 void initdfs()
 76 {
 77     CL(pre,-1);
 78     CL(tagp,0);
 79     CL(tag,0);
 80     CL(re,0);
 81     for(int i=0;i<MAXNODE;i++)fa[i]=i;
 82 }
 83
 84 void dfsad(int i,int pr)
 85 {
 86     pre[i]=pr;
 87     int p=head[i],v,t,k,pos,rt;
 88     while(p!=-1)
 89     {
 90         v=edge[p].v;
 91         if(pre[v]==-1)
 92         {
 93             etn[edge[p].p]=v;
 94             dfsad(v,i);
 95         }
 96         p=edge[p].next;
 97     }
 98     tag[i]=1;
 99     p=heado[i];
100     while(p!=-1)
101     {
102         v=op[p].v;
103         t=op[p].t;
104         k=op[p].k;
105         rt=fifa(v);
106         if(tag[v]==1&&tagp[op[p].p]==0)
107         {
108             re[i][t]+=k;re[v][t]+=k;
109             re[rt][t]-=k;
110             if(t==0)
111             {
112                 re[pre[rt]][t]-=k;
113             }
114             else re[rt][t]-=k;
115             tagp[op[p].p]=1;
116         }
117         p=op[p].next;
118     }
119     fa[i]=pr;
120 }
121
122 void dfs(int i,int pr)
123 {
124     tag[i]=1;
125     int p=head[i],v;
126     while(p!=-1)
127     {
128         v=edge[p].v;
129         if(tag[v]==0)dfs(v,i);
130         p=edge[p].next;
131     }
132     re[pr][0]+=re[i][0];
133     re[pr][1]+=re[i][1];
134 }
135
136 char opt[10];
137
138 int main()
139 {
140     int tt,ii;
141     cin>>tt;
142     for(ii=1;ii<=tt;ii++)
143     {
144         scanf("%d %d",&n,&q);
145         int i,j,a,b,k;
146         inithead();
147         initheado();
148         initdfs();
149         for(i=1;i<n;i++)
150         {
151             scanf("%d %d",&a,&b);
152             addedge(a,b,i);
153         }
154         for(i=1;i<=q;i++)
155         {
156             scanf("%s %d %d %d",opt,&a,&b,&k);
157             {
158                 if(opt[3]==‘1‘)
159                 {
160                     addo(a,b,0,k,i);
161                 }
162                 else
163                 {
164                     addo(a,b,1,k,i);
165                 }
166             }
167         }
168         dfsad(1,0);
169         CL(tag,0);
170         dfs(1,0);
171         printf("Case #%d:\n",ii);
172         for(i=1;i<=n;i++)
173         {
174             if(i!=1)printf(" ");
175             printf("%I64d",re[i][0]);
176         }cout<<endl;
177         for(i=1;i<n;i++)
178         {
179             if(i!=1)printf(" ");
180             printf("%I64d",re[etn[i]][1]);
181         }cout<<endl;
182     }
183     return 0;
184 }
时间: 2024-10-24 18:12:00

HDU 5044 离线LCA算法的相关文章

HDU 5452(离线LCA,树形dp

题目:给出一个图和它的一个生成树,要求删除生成树上的一条边和若干其他边,使得图不连通.求能删除的最小边数. 思路:考虑dp,对于树上的一条边,删除之后,还需要删除的边的数目就是从这个节点的子树连向其他子树或祖先节点的边数.那么对于一棵子树来说这个统计数目就等于其子树的数目之和减去它的子树之间的边数.减的这一部分可以在tarjan离线LCA算法中实现. /* * @author: Cwind */ //#pragma comment(linker, "/STACK:102400000,102400

hdu 2586 How far away ?(Tarjan离线LCA)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:对于一个有 n 个节点的图,有 n - 1 条无向边,权值给出.有 m 个查询, 每个查询 a b 表示询问 a b 两节点间的距离. 思路: 把这个联通图以树的形式表现出来,取任意两点,假设其最近公共祖先(Least Common Ancestors)为 lca,则两点间的距离等于: dis(a, b) = dis(a, root) + dis(b, root) - 2 * dis(r

LCA(最近公共祖先)——离线 Tarjan 算法

一.梳理概念 定义:对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. 通俗地讲,最近公共祖先节点,就是两个节点在这棵树上深度最大的公共的祖先节点,即两个点在这棵树上距离最近的公共祖先节点. 提示:父亲节点也是祖先节点,节点本身也是它的祖先节点. 给出一棵树,如图所示: 由上面的定义可知:3和5的最近公共祖先为1,5和6的最近公共祖先为2,2和7的最近公共祖先为2, 6和7的最近公共祖先为4. 二.繁文缛节 注意注意注意!!!尚

POJ 1330 LCA最近公共祖先 离线tarjan算法

题意要求一棵树上,两个点的最近公共祖先 即LCA 现学了一下LCA-Tarjan算法,还挺好理解的,这是个离线的算法,先把询问存贮起来,在一遍dfs过程中,找到了对应的询问点,即可输出 原理用了并查集和dfs染色,先dfs到底层开始往上回溯,边并查集合并 一边染色,这样只要询问的两个点均被染色了,就可以输出当前并查集的最高父亲一定是LCA,因为我是从底层层层往上DSU和染色的,要么没被染色,被染色之后,肯定就是当前节点是最近的 #include <iostream> #include <

最近公共祖先(LCA):离线&amp;在线算法

问题:求两个结点的最近公共祖先(即在树中的公共祖先中高度最低的祖先),下面介绍两种适用于不同场景的算法. Hiho15:离线Tarjan算法 基本思想 Tarjan算法适用于离线批量处理多个查询请求.基本思想是以深度优先搜索的顺序访问这颗树,给这棵树的结点染色,一开始所有结点都是白色的,而当第一次经过某个结点的时候,将它染成灰色,而当第二次经过这个结点的时候--也就是离开这棵子树的时候,将它染成黑色. 这样做的意义,举例说明,当我们深度优先搜索到A结点时,我们发现A结点和B结点是我们需要处理的一

HDU 2586 How far away ? 离线lca模板题

How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8712    Accepted Submission(s): 3047 Problem Description There are n houses in the village and some bidirectional roads connecting

POJ - 1470 Closest Common Ancestors(离线Tarjan算法)

1.输出测试用例中是最近公共祖先的节点,以及这个节点作为最近公共祖先的次数. 2.最近公共祖先,离线Tarjan算法 3. /* POJ 1470 给出一颗有向树,Q个查询 输出查询结果中每个点出现次数 */ /* 离线算法,LCATarjan 复杂度O(n+Q); */ #include<iostream> #include<stdio.h> #include<string.h> using namespace std; const int MAXN=1010; co

hihoCoder #1067 : 最近公共祖先&#183;二 [ 离线LCA tarjan ]

传送门: #1067 : 最近公共祖先·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho用非常拙劣——或者说粗糙的手段山寨出了一个神奇的网站,这个网站可以计算出某两个人的所有共同祖先中辈分最低的一个是谁.远在美国的他们利用了一些奇妙的技术获得了国内许多人的相关信息,并且搭建了一个小小的网站来应付来自四面八方的请求. 但正如我们所能想象到的……这样一个简单的算法并不能支撑住非常大的访问量,所以摆在小Hi和小Ho面前的无非两种选择: 其一是

hdu3078 建层次树+在线LCA算法+排序

题意:n个点,n-1条边构成无向树,每个节点有权,Q次询问,每次或问从a->b的最短路中,权第k大的值,/或者更新节点a的权, 思路:在线LCA,先dfs生成树0,标记出层数和fa[](每个节点的父亲节点).在对每次询问,走一遍一次公共祖先路上 的权,保持,快排.n*logn*q #include<iostream> //187MS #include<algorithm> #include<cstdio> #include<vector> using