【Foreign】旅行路线 [倍增]

旅行路线

Time Limit: 20 Sec  Memory Limit: 256 MB

Description

  

Input

  

Output

  仅一行一个整数表示答案。

Sample Input

  3
  2 1
  3 1

Sample Output

  3

HINT

  

Main idea

  将每个点的入度作为标识,问从叶节点到根有几个本质不同的串。

Solution

  我们先考虑暴力的写法,显然无重复的话是答案是ΣDep[i],那么我们构建出一棵树,然后从任意两个点暴力往上判断找到最长相同的长度,然后减去这个长度即可。

  我们发现这个算法慢在哪里?就是一步步判断太慢了!对于这种问题,我们显然可以使用倍增

  我们用字符串的哈希值来判断字符串是否相同,那么就记录一个hash[u][i]表示从u到往上跳(2^i)-1的哈希值,然后我们按照每个点到根的哈希值排序,显然得到的序列会满足:哈希值有相同的必然会在一起,若相同的长则会更接近。

  然后我们O(n)比较相邻两个的哈希值,用倍增来跳,找到最长长度减去即可。

Code

  1 #include<iostream>  
  2 #include<algorithm>  
  3 #include<cstdio>  
  4 #include<cstring>  
  5 #include<cstdlib>  
  6 #include<cmath>  
  7 using namespace std;
  8 typedef long long s64;
  9 const int ONE = 100005;
 10 const int INF = 214783640;
 11 const int P = 21;
 12 
 13 int n;
 14 int x,y; 
 15 int Input[ONE];
 16 int Dep[ONE],id[ONE];
 17 int f[ONE][22];
 18 s64 Q[ONE],hash[ONE][22];
 19 int next[ONE],first[ONE],go[ONE],tot;
 20 s64 Ans;
 21 
 22 int get()
 23 { 
 24         int res=1,Q=1;    char c;
 25         while( (c=getchar())<48 || c>57)
 26         if(c=='-')Q=-1;
 27         if(Q) res=c-48; 
 28         while((c=getchar())>=48 && c<=57) 
 29         res=res*10+c-48; 
 30         return res*Q; 
 31 }
 32 
 33 int Add(int u,int v)
 34 {
 35         next[++tot]=first[u];    first[u]=tot;    go[tot]=v;
 36 }
 37 
 38 void Dfs(int u)
 39 {
 40         hash[u][0] = Input[u];
 41         
 42         for(int i=0;i<=P-1;i++)
 43         {
 44             f[u][i+1] = f[f[u][i]][i];
 45             hash[u][i+1] = hash[u][i] + hash[f[u][i]][i] * Q[i];
 46         }
 47         
 48         for(int e=first[u];e;e=next[e])
 49         {
 50             int v=go[e];
 51             f[v][0] = u;
 52             Dep[v] = Dep[u] + 1;
 53             Dfs(v);
 54         }
 55 }
 56 
 57 bool cmp(int x,int y)
 58 {
 59         for(int i=P-1;i>=0;i--)
 60         if(Dep[x]>=(1<<i) && hash[x][i] == hash[y][i])
 61         {
 62             x = f[x][i];
 63             y = f[y][i];
 64         }
 65         return hash[x][0] < hash[y][0];
 66 }
 67 
 68 int Same(int x,int y)
 69 {
 70         int res=0;
 71         for(int i=P-1;i>=0;i--)
 72         if(Dep[x]>=(1<<i) && hash[x][i] == hash[y][i])
 73         {
 74             x = f[x][i];
 75             y = f[y][i];
 76             res += (1<<i);
 77         }
 78         return res;
 79 }
 80 
 81 int main()
 82 {
 83         n=get();
 84         for(int i=1;i<=n;i++) id[i]=i;
 85         for(int i=1;i<n;i++)
 86         {
 87             x=get();    y=get();
 88             Add(y,x);
 89             Input[x]++;    Input[y]++;
 90         }
 91         
 92         Q[0] = 1e9+7;
 93         for(int i=1;i<=P;i++) Q[i] = Q[i-1] * Q[i-1];
 94         
 95         Dep[1]=1;    Dfs(1);
 96         sort(id+1,id+n+1,cmp);
 97         
 98         Ans = Dep[id[1]];
 99         for(int i=2;i<=n;i++)
100         {
101             Ans += Dep[id[i]] - Same(id[i],id[i-1]);
102         }
103         
104         printf("%lld",Ans);
105 }
View Code

 

posted @ 2017-03-06 20:38  BearChild  阅读(201)  评论(0编辑  收藏  举报