• 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
    ", 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
    ",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
    ", 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("
    %s",str);
    75 //            printf("%s
    ",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
    ",ka++,_ans);
    86     }
    87 }
    View Code
  • 相关阅读:
    P1246 编码
    P2638 安全系统
    P3913 车的攻击
    P2789 直线交点数
    What?100%基于深度强化学习的对冲基金
    AI | 重磅推荐!哥大开源“FinRL”:一个用于量化金融自动交易的深度强化学习库
    神经霍克斯过程:一个基于神经网络的自调节多变量点过程
    量化都玩IPU了?Man Group-Oxford研究所给你答案
    为什么数字资产生态系统能够增长到2万亿美元以上?
    ICML 获奖者陆昱成:去中心化机器学习的理论极限在哪里?
  • 原文地址:https://www.cnblogs.com/zhanzhao/p/4773996.html
Copyright © 2020-2023  润新知