码迷,mamicode.com
首页 > 其他好文 > 详细

hdu--2586--lca_tarjan<证明tarjan这个人很流弊>

时间:2014-08-29 15:53:38      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   使用   io   ar   for   

开篇 敬仰下 大师-tarjan 发明的这些算法太流弊了=-=使用这个lca_tarjan之前 可以先去学习下使用tarjan解决scc强连通问题

我本来是去做到hdu-4912-发现做不来=-= 去网上搜了下 都说是神马lca的....那就去学下吧 而且很多也将这题当做入门题..

lca分离线和在线 这边我介绍的是离线算法 是要先将所有的询问一起处理 而不是单个单个地去处理  处理完成之后 你自己选择一种方式将答案存储下来

然后再进行一遍输出答案

我再网上没有找到一篇好的博客来推荐给大家 所以这边我就不写 传送门的故事了 -.-

学习下它 对于你的思想 是很有帮助的 很多时候 都是这样

这边我们需要用到 并查集来优化这个算法

我们结合下图 进行分析

bubuko.com,布布扣

 

现在 我们以上图为例 建立的边<无向>

1<-->2   2<-->3   2<--->4   3<--->5   5<--->7   2<--->4  4<--->6  1<--->8  8<--->9

我们的询问就是

lca:<2,3>  ,   <5,6>    ,    <7,4>      ,    <9,3>

这4组查询结果也算都是有一些特点的吧  虽然我们很容易地可以从上图中得到结果

2 3肯定是2啊 因为3是2的子树下的结点

5 6就是2了 他们同时是2的子树的结点 你也当然会说他们也是1的子树的结点啊 但是2的深度更大 离根结点更远

还有2个就先不说了.....

既然 这是树 那我们解决的时候首先就自己确定一个根结点 按习惯上 我们都喜欢默认1当做根结点 当然你也可以2 3 ……n

草。。我突然发现 不会分析下去了..

就是要注意下 假设你当前访问到的结点是u 现在有一个结点是v与u相邻 那么假如v没有被访问过 那就再lca_tarjan(v)即去访问v 这边的后续操作要明白 既然u与v相邻 那我们可以将他们看成是在同一棵子树上的 所以我们将v所在的集合并在u所在的集合之下 这时 就需要用到并查集了  这边一定是要 father[ find(v) ] = find(u) 当然这个指向的前提是u v的find后不属于同一个集合

可能有些 言不达意 =-= 都是自我理解 大家可以多参考一些博客 然后自己模拟画画 就是了

 

bubuko.com,布布扣
  1 #include <iostream>
  2 #include <cstring>
  3 using namespace std;
  4 
  5 int cnt1 , cnt2;
  6 const int size1 = 40010;
  7 const int size2 = 210;
  8 struct graph
  9 {
 10     int from;
 11     int to;
 12     int val;
 13     int next;
 14     int lca;
 15 };
 16 graph edge[size1*2];
 17 int Ehead[size1];
 18 graph node[size2*2];
 19 int Nhead[size1];
 20 bool vis[size1];
 21 int dist[size1];
 22 int father[size1];
 23 
 24 void init( )
 25 {
 26     memset( Ehead , -1 , sizeof(Ehead) );
 27     memset( Nhead , -1 , sizeof(Nhead) );
 28     memset( dist , 0 , sizeof(dist) );
 29     memset( vis , false , sizeof(vis) );
 30 }
 31 
 32 int find( int x )
 33 {
 34     return x == father[x] ? x : father[x] = find( father[x] );
 35 }
 36 
 37 
 38 void addEdge( int from , int to , int val )
 39 {
 40     edge[cnt1].to = to;
 41     edge[cnt1].val = val;
 42     edge[cnt1].next = Ehead[from];
 43     Ehead[from] = cnt1 ++;
 44 }
 45 
 46 void addQueryEdge( int from , int to )
 47 {
 48     node[cnt2].from = from;
 49     node[cnt2].to = to;
 50     node[cnt2].next = Nhead[from];
 51     Nhead[from] = cnt2 ++;
 52 }
 53 
 54 void lca_tarjan( int u , int val )
 55 {
 56     int v , x , y;
 57     vis[u] = true;
 58     dist[u] = val;
 59     father[u] = u;
 60     for( int i = Ehead[u] ; ~i ; i = edge[i].next )
 61     {
 62         v = edge[i].to;
 63         if( !vis[v] )
 64         {
 65             lca_tarjan( v , edge[i].val + val );
 66             x = find(u);
 67             y = find(v);
 68             if( x!=y )
 69             {
 70                 father[y] = x;
 71             }
 72         }
 73     }
 74     for( int i = Nhead[u] ; ~i ; i = node[i].next )
 75     {
 76         v = node[i].to; 
 77         if( vis[v] )
 78         {
 79             node[i].lca = node[i^1].lca = find(v);
 80         }
 81     }
 82 }
 83 
 84 int main()
 85 {
 86     cin.sync_with_stdio(false);
 87     int t , from , to , val , ans , id;
 88     int n , m;
 89     cin >> t;
 90     while( t-- )
 91     {
 92         init( );
 93         cin >> n >> m;
 94         cnt1 = cnt2 = 0;
 95         for( int i = 1 ; i<n ; i++ )
 96         {
 97             cin >> from >> to >> val;
 98             addEdge( from , to , val );
 99             addEdge( to , from , val );
100         }
101         for( int i = 0 ; i<m ; i++ )
102         {
103             cin >> from >> to;
104             addQueryEdge( from , to );
105             addQueryEdge( to , from );
106         }
107         lca_tarjan( 1 , 0 );
108         for( int i = 0 ; i<m ; i++ )
109         {
110             id = i * 2;
111             ans = dist[ node[id].from ] + dist[ node[id].to ] - 2*dist[ node[id].lca ];
112             cout << ans << endl;
113         }
114     }
115     return 0;
116 }
View Code

忘了一个很重要的...lca是基于 无向无环图的 也可以说多叉树吧 我是觉得差不多的

 

today:

  我们最大的敌人就是自己

  我们的恐惧来源于对自己的否定

  信心才是最重要的

 

hdu--2586--lca_tarjan<证明tarjan这个人很流弊>

标签:style   blog   http   color   os   使用   io   ar   for   

原文地址:http://www.cnblogs.com/radical/p/3945072.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!