大意:告诉你一些字符串 让你组成字典树,
然后定义每个节点到所有叶子节点的距离的和等于改点的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 }
第二种方法 直接对每个点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 }
时间: 2024-11-02 02:49:00