HDU4547+LCA

有向边!!!

  1 #include<stdio.h>
  2 #include<string>
  3 #include<map>
  4 #include<stdlib.h>
  5 #include<iostream>
  6 #include<algorithm>
  7 #include<math.h>
  8 using namespace std;
  9 const int maxn = 200005;
 10 struct node{
 11     int from,to,next,val;
 12 }edge[ maxn<<2 ];
 13 int cnt,head[ maxn ];
 14 map<string,int>mp;
 15 
 16 void addedge( int a,int b,int c ){
 17     edge[ cnt ].from = a;
 18     edge[ cnt ].to = b;
 19     edge[ cnt ].next = head[ a ];
 20     head[ a ] = cnt++;
 21 }
 22 int ace[ maxn ];//最近公共祖先
 23 int deep[ maxn ];
 24 int fa[ maxn ];
 25 int dis[ maxn ];
 26 
 27 void init(){
 28     cnt = 0;
 29     mp.clear();
 30     memset( fa,0,sizeof(fa) );
 31     memset( head,-1,sizeof( head ) );
 32 }
 33 
 34 void dfs( int now,int now_father,int now_ace,int now_deep,int now_dis ){
 35     fa[ now ]=now_father;
 36     deep[ now ]=now_deep;
 37     dis[ now ]=now_dis;
 38     ace[ now ]=now_ace;
 39     for( int i=head[ now ];i!=-1;i=edge[ i ].next ){
 40         int v=edge[ i ].to;
 41        // if( fa[ v ]==0 )
 42             dfs( v,now,now_ace,now_deep+1,now_dis+edge[ i ].val );
 43     }
 44 }
 45 
 46 int find( int x,int y ){
 47     if( x==y ) return x;
 48     if( deep[ x ]>deep[ y ] ){
 49         return find( fa[x],y );
 50     }
 51     else{
 52         return find( x,fa[y] );
 53     }
 54 }
 55 
 56 int main(){
 57     int ca;
 58     scanf("%d",&ca);
 59     while( ca-- ){
 60         int n,m;
 61         scanf("%d%d",&n,&m);
 62         init();
 63         string a,b;
 64         int num1,num2;
 65         int cc = 1;
 66         for( int i=0;i<n-1;i++ ){
 67             cin>>a>>b;
 68             if( mp[a]==0 ){
 69                 mp[a] = cc;
 70                 num1 = cc;
 71                 cc++;
 72             }
 73             else num1 = mp[a];
 74             if( mp[b]==0 ){
 75                 mp[b] = cc;
 76                 num2 = cc;
 77                 cc++;
 78             }
 79             else num2 = mp[b];
 80             addedge( num2,num1,1 );
 81             //addedge( num1,num2,1 );
 82             //cout<<a<<"="<<num1<<" ";
 83             //cout<<b<<"="<<num2<<endl;
 84         }
 85         for( int i=1;i<cc;i++ ){
 86             if( fa[i]==0 ){    
 87                 dfs( i,-1,i,0,1 );
 88             }
 89         }
 90         /*
 91         for( int i=1;i<cc;i++ ){
 92             printf("now = %d\n",i);
 93             printf("dis[%d]=%d ace[%d]=%d fa[%d]=%d deep[%d]=%d\n\n",i,dis[i],i,ace[i],i,fa[i],i,deep[i]);
 94         }
 95         */
 96         while( m-- ){
 97             cin>>a>>b;
 98             num1 = mp[a];
 99             num2 = mp[b];
100             int father = find( num1,num2 );
101             if( father==num2 ){
102                 printf("%d\n",abs(deep[num2]-deep[num1]));
103             }
104             else if( father==num1 ){
105                 printf("1\n");
106             }
107             else{
108                 printf("%d\n",abs(deep[num1]-deep[father])+1);
109             }
110 
111         }
112     }
113     return 0;
114 }
View Code

再贴一个tarjan版本的。。。

  1 /*
  2 lca+tarjan
  3 */
  4 #include<stdio.h>
  5 #include<string.h>
  6 #include<stdlib.h>
  7 #include<algorithm>
  8 #include<iostream>
  9 #include<queue>
 10 #include<map>
 11 #include<math.h>
 12 using namespace std;
 13 typedef long long ll;
 14 //typedef __int64 int64;
 15 const int maxn = 100105;
 16 const int inf = 0x7fffffff;
 17 const double pi=acos(-1.0);
 18 const double eps = 1e-8;
 19 
 20 int fa[ maxn ],ace[ maxn ],dis[ maxn ],vis[ maxn ];
 21 struct node{
 22     int u,next;
 23 }edge[ maxn<<4 ],ex_edge[ maxn<<4 ];
 24 struct  node2{
 25     int u,next,val;
 26 }ans_edge[ maxn ];
 27 struct  node3{
 28     int u,v,fa;
 29 }query[ maxn ];
 30 int cnt,head[ maxn ],ex_cnt,ex_head[ maxn ],ans_cnt,ans_head[ maxn ];
 31 map<string,int>mp;
 32 
 33 void init(){
 34     cnt = ex_cnt = ans_cnt = 0;
 35     mp.clear();
 36     memset( ans_head,-1,sizeof( ans_head ) );
 37     memset( ex_head,-1,sizeof( ex_head ) );
 38     memset( head,-1,sizeof( head ) );
 39 }
 40 void addedge( int a,int b ){
 41     edge[ cnt ].u = b;
 42     edge[ cnt ].next = head[ a ];
 43     head[ a ] = cnt++;
 44 }
 45 void ex_addedge( int a,int b ){
 46     ex_edge[ ex_cnt ].u = b;
 47     ex_edge[ ex_cnt ].next = ex_head[ a ];
 48     ex_head[ a ] = ex_cnt++;
 49 }
 50 void ans_addedge( int a,int b,int c ){
 51     ans_edge[ ans_cnt ].u = b;
 52     ans_edge[ ans_cnt ].val = c;
 53     ans_edge[ ans_cnt ].next = ans_head[ a ];
 54     ans_head[ a ] = ans_cnt++;
 55 }
 56 void make_set( int x ){
 57     fa[x] = x;
 58 }
 59 
 60 int file_root;
 61 void dfs( int cur ){
 62     if( vis[ cur ]==1 ) return ;
 63     vis[ cur ] = 1;
 64     file_root = cur;
 65     for( int i=ex_head[ cur ];i!=-1;i=ex_edge[ i ].next ){
 66         if( vis[ ex_edge[ i ].u ]==0 ){
 67             dfs( ex_edge[ i ].u );
 68         }
 69     }
 70 }//寻找根目录
 71 
 72 int find( int x ){
 73     if( fa[x]==x ) return x;
 74     return fa[x] = find( fa[x] );
 75 }
 76 
 77 void tarjan_of_lca( int cur,int dist ){
 78     make_set( cur );
 79     vis[ cur ] = 1;
 80     dis[ cur ] = dist;
 81     for( int i=head[ cur ];i!=-1;i=edge[ i ].next ){
 82         if( vis[ edge[ i ].u ]==0 ){
 83             tarjan_of_lca( edge[ i ].u,dist+1 );
 84             fa[ edge[ i ].u ] = cur;
 85         }
 86     }
 87     for( int i=ans_head[ cur ];i!=-1;i=ans_edge[ i ].next ){
 88         if( vis[ ans_edge[ i ].u ]==1 ){
 89             int father = find( ans_edge[ i ].u );
 90             query[ ans_edge[ i ].val ].fa = father;
 91             //printf("cur=%d,nxt=%d,father=%d\n",cur,ans_edge[ i ].u,father);
 92             //printf("dis_cur=%d,dis_nxt=%d,dis_fa=%d\n\n",dis[cur],dis[ans_edge[ i ].u],dis[father]);
 93         }
 94     }//在这里寻找公共祖先,至于原因与dfs的过程有关
 95 } 
 96 
 97 int main(){
 98     int ca;
 99     scanf("%d",&ca);
100     while( ca-- ){
101         int n,m;
102         scanf("%d%d",&n,&m);
103         init();
104         string a,b;
105         int f1,f2;
106         int cc = 1;
107         n--;
108         while( n-- ){
109             cin>>a>>b;
110             if( mp[a]==0 ) mp[a] = cc++;
111             if( mp[b]==0 ) mp[b] = cc++;
112             f1 = mp[a];
113             f2 = mp[b];
114             addedge( f2,f1 );
115             ex_addedge( f1,f2 );
116         }
117         file_root  = -1;
118         memset( vis,0,sizeof( vis ) );
119         dfs( f1 );//find the root
120         for( int i=1;i<=m;i++ ){
121             cin>>a>>b;
122             f1 = mp[a];
123             f2 = mp[b];
124             ans_addedge( f1,f2,i );
125             ans_addedge( f2,f1,i );//存边 便于在tarjan的过程中存下最近公共祖先
126             query[ i ].u = f1;
127             query[ i ].v = f2;//query记录询问的节点
128         }
129         memset( vis,0,sizeof( vis ) );
130         tarjan_of_lca( file_root,0 );
131         for( int i=1;i<=m;i++ ){
132             if( query[ i ].u==query[ i ].v ) printf("0\n");
133             else if( query[ i ].fa==query[ i ].u ) printf("1\n");
134             else if( query[ i ].fa==query[ i ].v ) printf("%d\n",abs( dis[ query[ i ].u ]-dis[ query[ i ].v ]));
135             else {
136                 printf("%d\n",dis[query[ i ].u]-dis[ query[ i ].fa ]+1);
137             }
138             //printf("%d\n",ans[i]);
139         }
140     }
141     return 0;
142 }
View Code

lca的tarjan版本过程很重要,在dfs过程中,当遇到询问的一对点时候,就要求出结果ace

posted @ 2013-05-22 18:36  xxx0624  阅读(275)  评论(0编辑  收藏  举报