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

你可能感兴趣的:(HDU)