• 2020 HZNU Winter Training Day 9 BC题解


    B题

    题意:

    给一棵树,找到三个顶点,使三个顶点两两之间路径的并集最大

    输出:

    三个顶点两两之间路径的并集的最大数量,以及这三个点的编号

    解析:

    用两次BFS可以求出树的直径的两个端点(假设为a,b),在这个过程中还能顺便求出一个端点到树上每一点的距离。

    之后再用一次BFS求得另一个端点到树上每一点的距离。

    最后枚举点c,满足c到a和c到b的距离和最大。

    a,b,c即为所求三点。

    最终数量为:[dis(a,b)+dis(b,c)+dis(a,c)]/2

     1 #include<cstdio>
     2 #include<cmath>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<cstring>
     6 #include<queue>
     7 using namespace std;
     8 const int maxn = 200000 + 10;
     9 const int maxm = 400000 + 10;
    10 inline int read() {
    11     char ch = getchar(); int x = 0, f = 1;
    12     while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    13     while ('0' <= ch && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    14     return x * f;
    15 }
    16 int n, a, b, c, pos;
    17 int dis[maxn], dis1[maxn], dis2[maxn], vis[maxn];
    18 int head[maxn], ver[maxm], Next[maxm], tot;
    19 void add(int u, int v) {
    20     ++tot;
    21     ver[tot] = v;
    22     Next[tot] = head[u];
    23     head[u] = tot;
    24 }
    25 
    26 void init() {
    27     memset(head, -1, sizeof head);
    28     tot = 0;
    29 }
    30 void bfs(int x) {
    31     queue<int>q;
    32     memset(vis, false, sizeof vis);
    33     memset(dis, 0, sizeof dis);
    34     pos = x;
    35     vis[x] = 1;
    36     dis[x] = 0;
    37     q.push(x);
    38     while (!q.empty()) {
    39         int u = q.front(); q.pop();
    40         for (int i = head[u]; i != -1; i = Next[i]) {
    41             int y = ver[i];
    42             if (!vis[y]) {
    43                 vis[y] = 1;
    44                 dis[y] = dis[u] + 1;
    45                 if (dis[y] > dis[pos])pos = y;
    46                 q.push(y);
    47             }
    48         }
    49     }
    50 }
    51 int main() {
    52     init();
    53     n = read();
    54     for (int i = 1; i < n; ++i) {
    55         int x = read(), y = read();
    56         add(x, y), add(y, x);
    57     }
    58     bfs(1); a = pos;
    59     bfs(pos); b = pos;
    60     //printf("%d %d
    ", a, b);
    61     for (int i = 1; i <= n; ++i)dis1[i] = dis[i];
    62     bfs(pos);
    63     for (int i = 1; i <= n; ++i)dis2[i] = dis[i];
    64     c = 0;
    65     for (int i = 1; i <= n; ++i) {
    66         if (dis1[i] + dis2[i] > dis1[c] + dis2[c] && i != a && i != b)c = i;
    67     }
    68     printf("%d
    ", (dis1[b] + dis1[c] + dis2[c]) / 2);
    69     printf("%d %d %d
    ", a, b, c);
    70 }

    C题

    题意:

    给定两个字符串s和t,你有一个空字符串z

    每次可以取s的任意一个子序列加到z后面

    问至少要取多少次才能让z等价于t

    解析:

    vector存s字符串中26个字母的位置

    然后t字符串从前往后一个个查找

    用变量now记录查到上一个字符时在字符串s中的位置(初始化为0)。

    如果在t内碰到一个字符,没有在s中出现过,输出-1结束当次程序

    否则,看当前的now是否大于等于这个字符在s中出现的最后一个位置,如果是,说明这一次子序列已经不能往后面取了,说明得另起一次从头取子序列,让now等于当前字符在s中出现的第一个位置;如果不是则二分找大于now的第一个这个字符的位置,让now等于这个位置即可。

     1 #include<cstdio>
     2 #include<cmath>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<cstring>
     6 #include<vector>
     7 using namespace std;
     8 #define ll long long
     9 const int inf = 0x3f3f3f3f;
    10 const int maxn = 100000 + 10;
    11 inline ll read() {
    12     char ch = getchar(); ll x = 0, f = 1;
    13     while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    14     while ('0' <= ch && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    15     return x * f;
    16 }
    17 vector<int >v[30];
    18 char s[maxn], t[maxn];
    19 int main() {
    20     int T = read();
    21     while (T--) {
    22         scanf("%s", s + 1);
    23         scanf("%s", t + 1);
    24         for (int i = 0; i <= 26; ++i) {
    25             v[i].clear();
    26         }
    27         int slen = strlen(s + 1);
    28         bool ok = false;
    29         for (int i = 1; i <= slen; ++i) {
    30             v[s[i] - 'a'].push_back(i);
    31         }
    32         int now = 0;
    33         int tlen = strlen(t + 1);
    34         int res = 0;
    35         for (int i = 1; i <= tlen; ++i) {
    36             int y = t[i] - 'a';
    37             if (v[y].size() == 0) {
    38                 ok = true;
    39                 break;
    40             }
    41             int l = 0, r = v[y].size() - 1;
    42             int ans = inf;
    43             while (l <= r) {
    44                 int mid = (l + r) >> 1;
    45                 if (v[y][mid] > now) {
    46                     ans = v[y][mid];
    47                     r = mid - 1;
    48                 }
    49                 else l = mid + 1;
    50             }
    51             if (ans == inf)res++, now = v[y][0];
    52             else now = ans;
    53             //printf("%d
    ", now);
    54         }
    55         res++;
    56         if (ok)puts("-1");
    57         else {
    58             printf("%d
    ", res);
    59         }
    60     }
    61 }
  • 相关阅读:
    ie不支持 event.stopPropagation 的解决方式
    jquery 获取 元素.text( ) 里面的值 需要进行去空格去换行符操作
    使用插件实现某元素展示特定行文字,超出显示...
    css文字超出显示省略号
    纯css实现各种三角形图案
    jQuery判断鼠标是否在某个元素内
    z-tree相关设置
    js提取字符串中的汉字
    扩展ie中不兼容的startsWith,endsWith方法
    获取浏览器URL携带过来的参数/获取url中"?"符后的字串
  • 原文地址:https://www.cnblogs.com/JayShao/p/12266935.html
Copyright © 2020-2023  润新知