hust1350Trie【字典树+dfs || 字典树 + LCA】

大意:告诉你一些字符串 让你组成字典树,

 

然后定义每个节点到所有叶子节点的距离的和等于改点的value

当根节点只有一个孩子,该根节点也算一个叶子节点

问所有节点的value的最小值

 

分析:

开始做的时候  就想的是   枚举每个点  然后求它到所有叶子节点的和  求任意两点的最近距离  用公共祖先来求 

于是就有了这个算法

需要预处理出来所有的叶子节点  

不能单纯的用字典树的flag来记录  例如插入aaa aa a  那么 a  aa aaa 都会被当成叶子节点  

对于这里的处理 我是排了一次序  把节点的最后值用flag标记

然后就是判断根节点是否只有一个孩子 

如果只有孩子  那么就加入孩子节点的数组

代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<queue>
  6 #include<vector>
  7 #include <set>
  8 using namespace std;
  9 
 10 const int MAXN = 100010;
 11 const int PP = 30;
 12 const int maxn = MAXN;
 13 
 14 
 15 int tire[maxn][30];
 16 int flag[maxn];
 17 int ceng[maxn];
 18 
 19 class LCA_RMQ
 20 {
 21 public:
 22     int n;
 23     int pow2[PP]; 
 24     int tim;
 25     int first[MAXN]; 
 26     int nodeId[MAXN*2]; 
 27     int dep[MAXN*2]; 
 28     int dp[MAXN*2][PP]; 
 29     bool vis[MAXN]; 
 30     vector<int> edge[MAXN];
 31 
 32     void init(int n)
 33     {
 34         for(int i = 0; i < PP; i++)
 35             pow2[i] = (1<<i);
 36 
 37         for(int i = 0; i <= n; i++)
 38         {
 39             edge[i].clear();
 40             vis[i] = false;
 41         }
 42 
 43     }
 44 
 45     void addedge(int u ,int v)
 46     {
 47         edge[u].push_back(v);
 48     }
 49 
 50     void dfs(int u ,int d) 
 51     {
 52         tim++;  
 53         vis[u] = true;
 54         nodeId[tim] = u;
 55         first[u] = tim; 
 56         dep[tim] = d;  
 57         int sz = edge[u].size();
 58         for(int i = 0; i < sz; i++)
 59         {
 60             int v = edge[u][i];
 61             if(vis[v] == false)
 62             {
 63                 dfs(v, d + 1);
 64                 tim++;
 65                 nodeId[tim] = u;  
 66                 dep[tim] = d;
 67             }
 68         }
 69     }
 70 
 71     void ST(int len)
 72     {
 73         int k = (int)(log(len+1.0) / log(2.0));
 74 
 75         for(int i = 1; i <= len; i++)
 76             dp[i][0] = i;
 77 
 78         for(int j = 1; j <= k; j++)
 79             for(int i = 1; i + pow2[j] - 1 <= len; i++)
 80             {
 81                 int a = dp[i][j-1]; 
 82                 int b = dp[i+pow2[j-1]][j-1];
 83                 if(dep[a] < dep[b]) dp[i][j] = a;
 84                 else dp[i][j] = b;
 85             }
 86     }
 87 
 88     int RMQ(int x ,int y)
 89     {
 90         int k = (int)(log(y-x+1.0) / log(2.0));
 91         int a = dp[x][k];
 92         int b = dp[y-pow2[k]+1][k];
 93         if(dep[a] < dep[b]) return a;
 94         else return b;
 95     }
 96 
 97     int LCA(int u ,int v)
 98     {
 99         if(u > v) swap(u, v);
100         int x = first[u];
101         int y = first[v];
102         if(x > y) swap(x,y);
103         int index = RMQ(x,y);
104         return nodeId[index];
105     }
106 };
107 LCA_RMQ t;
108 
109 int tot;
110 void Insert(string s,int rt)
111 {
112     ceng[rt] = 0;
113     int len=s.length();
114     for(int i=0;i<len;i++)
115     {
116         int x=s[i]-'a';
117         if(tire[rt][x]==0) {
118             tire[rt][x]=tot++;
119             ceng[tire[rt][x]] = i + 1;
120             t.addedge(rt, tire[rt][x]);
121         }
122 //rt        printf("%c %d  %d\n", x + 'a', tire[rt][x], ceng[tire[rt][x]]);
123         rt=tire[rt][x];
124         flag[rt] = 0;
125     }
126     flag[rt]=1;
127 }
128 
129 char str[55][15];
130 set<string> ss;
131 int ye[maxn];
132 int main()
133 {
134     int tt;
135     scanf("%d",&tt);
136     for(int kase = 1; kase <= tt; kase++) {
137         int n;
138         scanf("%d",&n);
139         tot = 1;
140         memset(tire, 0, sizeof(tire));
141         memset(flag, 0, sizeof(flag));
142         memset(ceng, 0, sizeof(ceng));
143         tot = 2;
144         t.init(100000);
145         ss.clear();
146         string s1;
147         for(int i = 0; i < n; i++) {
148             getchar();
149             cin >> s1;
150             ss.insert(s1);    
151         }
152 
153     set<string>::iterator it;
154 for(it = ss.begin(); it != ss.end(); it++) {
155     s1 = *it;
156     Insert(s1, 1);
157 }    
158         t.n = tot;
159         t.tim = 0;
160         t.dfs(1, 1);
161         t.ST(2 * t.n - 1);
162         int ye_tot = 0;
163         for(int i = 1; i < tot; i++) {
164             if(flag[i] == true) {
165                 ye[ye_tot++] = i;
166             }
167         }
168         int hh = 0;
169         for(int i = 0; i < 26; i++) {
170             if(tire[1][i] != 0) {
171                 hh++;
172             }
173         }
174         if(hh == 1) {
175             ye[ye_tot++] = 1;
176         }
177 //        for(int i = 0; i< ye_tot; i++) {
178 //            printf("%d ", ye[i]);
179 //        }puts("");
180         int ans = 1000000000;
181         for(int i = 1; i < tot; i++) {
182             int sum = 0;
183             for(int j = 0; j < ye_tot; j++) {
184                 int rt = t.LCA(i, ye[j]);
185                 sum += fabs(ceng[i] - ceng[rt]) + fabs(ceng[ye[j]] - ceng[rt]);
186             }
187             
188             ans = min(ans, sum);
189         }
190         printf("Case #%d: %d\n",kase, ans);
191     }
192     return 0;
193 }
View Code

 

第二种方法  直接对每个点dfs  由于总共的点数为500个  所用时间复杂度用500*500  

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 
 6 const int maxn = 505;
 7 
 8 
 9 struct Edge {
10     int to, next;
11 }e[maxn];
12 int sum;
13 int head[maxn];
14 
15 void add(int u, int v) {
16     e[sum].to = v;
17     e[sum].next = head[u];
18     head[u] = sum++;
19 }
20 
21 
22 int tire[maxn][30];
23 int tot;
24 
25 
26 void init() {
27     memset(tire, 0, sizeof(tire));
28     memset(head, 0, sizeof(head));
29     sum = 1;
30     tot = 1;
31 }
32 
33 void Insert(char *s, int rt) {
34     for(int i = 0; s[i]; i++) {
35         int x = s[i] - 'a';
36         if(tire[rt][x] == 0) {
37             tire[rt][x] = tot++;
38             add(rt, tire[rt][x]);
39             add(tire[rt][x], rt);
40         }
41 //        printf("%c   %d\n", s[i], tire[rt][x]);
42         rt = tire[rt][x];
43     }
44 }
45 
46 int ans;
47 
48 int vis[maxn];
49 void dfs(int u, int de) {
50     vis[u] = 1;
51     bool flag = false;
52     for(int i = head[u]; i; i = e[i].next) {
53         int v = e[i].to;
54         if(!vis[v]) {
55             vis[v] = 1;
56             flag = true;
57             dfs(v, de + 1);
58         }
59     }
60     if(flag == false) {
61         ans += de;
62     }
63 }
64 
65 int main() {
66     int t, n;
67     char str[15];
68     scanf("%d",&t);
69     int ka = 1;
70     while(t--) {
71         scanf("%d",&n);
72         init();
73         while(n--) {
74             scanf("\n%s",str);
75 //            printf("%s\n",str);
76             Insert(str, 0);
77         }
78         int _ans = 1000000000;
79         for(int i = 0; i < tot; i++) {
80             ans = 0;
81             memset(vis, 0, sizeof(vis));
82             dfs(i, 0);
83             _ans = min(_ans, ans);
84         }
85         printf("Case #%d: %d\n",ka++,_ans);
86     }
87 }
View Code

 

posted @ 2015-08-31 20:15  悠悠我心。  阅读(263)  评论(0编辑  收藏  举报