日常刷题2025-2-26

日常刷题2025-2-26

E - Palindromic Shortest Path

rating:1500

https://atcoder.jp/contests/abc394/tasks/abc394_e

思路:BFS

做有关回文的题,思考方式应该是考虑长度长的回文如何用长度短的回文得到,以一种递推的方式得到所有回文。

https://www.bilibili.com/video/BV1E2ASeiE8b/?spm_id_from=333.1387.upload.video_card.click&vd_source=4a339d299e165d8fe38b9926c5240eae

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 105;
const int N2 = N * N;

int n, ans[N][N];
char s[N][N];
int q[N2][2];

int main() {
  scanf("%d", &n);
  for(int i = 1; i <= n; i++) {
    scanf("%s", s[i] + 1);
  }

  int hd = 1, tl = 0;
  memset(ans, 0x3f, sizeof(ans));

  for(int i = 1; i <= n; i++) {
    ans[i][i] = 0;
    q[++tl][0] = i; q[tl][1] = i;
    // (i, i) : 0 入队
  }
  for(int i = 1; i <= n; i++) {
    for(int j = 1; j <= n; j++) {
      if(i != j && s[i][j] != '-') {
        ans[i][j] = 1;
        q[++tl][0] = i; q[tl][1] = j;
        // (i, j) : 1 入队
      }
    }
  }
  while(hd <= tl) {
    int u = q[hd][0], v = q[hd][1];
    // 取出状态 (u, v)
    hd++;
    for(int i = 1; i <= n; i++) if(s[i][u] != '-') {
      for(int j = 1; j <= n; j++) if(s[v][j] == s[i][u]) {
        // 扩展后的状态 (i, j)
        if(ans[i][j] == 0x3f3f3f3f) {
          ans[i][j] = ans[u][v] + 2;
          q[++tl][0] = i; q[tl][1] = j;
        }
      }
    }
  }
  for(int i = 1; i <= n; i++) {
    for(int j = 1; j <= n; j++) {
      if(ans[i][j] == 0x3f3f3f3f) {
        printf("-1 ");
      } else {
        printf("%d ", ans[i][j]);
      }
    }
    puts("");
  }

  return 0;
}

F - Alkane

rating:1500

https://atcoder.jp/contests/abc394/tasks/abc394_f

思路:树形DP

https://www.bilibili.com/video/BV1E2ASeiE8b/?spm_id_from=333.1387.upload.video_card.click&vd_source=4a339d299e165d8fe38b9926c5240eae

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n, d[N], f[N][2], ans;
vector<int> G[N];
bool vis[N];

void dfs(int u) {
  vis[u] = true;
  vector<int> tmp;
  for(int v : G[u]) if(d[v] >= 4 && !vis[v]) {
    dfs(v);
    tmp.push_back(f[v][1]);
  }
  sort(tmp.rbegin(), tmp.rend()); // 从大到小把儿子排序了
  f[u][1] = 1; // 选最大的三个儿子
  for(int i = 0; i < tmp.size() && i < 3; i++) {
    f[u][1] += tmp[i];
  }

  // f[u][0] 选最大的四个儿子
  f[u][0] = f[u][1];
  if(tmp.size() >= 4) f[u][0] += tmp[3];
  ans = max(ans, f[u][0]);
}

int main() {
  scanf("%d", &n);
  for(int i = 1; i < n; i++) {
    int u, v;
    scanf("%d %d", &u, &v);
    G[u].push_back(v);
    G[v].push_back(u);
    d[u]++;
    d[v]++;
  }
  for(int i = 1; i <= n; i++) {
    if(d[i] >= 4 && !vis[i]) {
      dfs(i);
    }
  }
  if(ans == 0) printf("-1\n");
  else printf("%d\n", ans * 3 + 2);

  return 0;
}
posted @ 2025-02-26 10:05  califeee  阅读(28)  评论(0)    收藏  举报