牛客月赛106(0/1最短路,树存最长链)

[复制链接]
发表于 2025-12-8 17:09:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
目次
        A. 末了DISCO
        D. 太阳系DISCO
        E. 平凡DISCO-1


 
 
 
 
A. 末了DISCO


        (1)pow(a, b) :a ^ b
        (2)数据范围,爆long long。因此直接判 a ^ b 的奇偶,奇赋值 1 ,偶赋值 0
        (3)注意 b 大概为 0

  1. #include<bits/stdc++.h>
  2. #define LL long long
  3. using namespace std;
  4. LL a, b, c, d, n, ans;
  5. int main()
  6. {
  7.         cin >> a >> b >> c >> d;
  8.         LL t1 = 2;
  9.         if (a % 2 != 0 || b == 0)
  10.                 t1 = 1;
  11.         ans = t1 * c + d;
  12.         if (ans % 2 == 0)
  13.                 cout << "NO";
  14.         else
  15.                 cout << "YES";
  16.         return 0;
  17. }
复制代码
 




D. 太阳系DISCO


        (1)标题实质为最短路,每次耗费均为 1,用 bfs 即可
        (2)逆时针走 y 步,即为顺时针走 n - y 步,题中规定 y < n,否则模前要 + n
        (3)每一个队首出队都有顺 / 逆两种选择,到达的两个点都入队
        (4)技能最多用一次,用两次便是没用。和不消技能作比力
        (5)技能在哪用都一样,那就选择体如今末了一次上

  1. #include<bits/stdc++.h>
  2. #define LL long long
  3. using namespace std;
  4. const int N = 2e5 + 5, INF = 0x3f3f3f3f;
  5. int n, k, a, b, x, y, ans, dis[N];
  6. queue <int> q;
  7. int main()
  8. {
  9.         cin >> n >> k >> a >> b >> x >> y;
  10.         memset(dis, 0x3f, sizeof(dis));
  11.         q.push(a), dis[a] = 0;
  12.         while (q.size())
  13.         {
  14.                 int p = q.front();
  15.                 q.pop();
  16.                 int e1 = (p + x) % n;
  17.                 if (dis[e1] > dis[p] + 1)
  18.                 {
  19.                         dis[e1] = dis[p] + 1;
  20.                         q.push(e1);
  21.                 }
  22.                 int e2 = (p + n - y) % n;
  23.                 if (dis[e2] > dis[p] + 1)
  24.                 {
  25.                         dis[e2] = dis[p] + 1;
  26.                         q.push(e2);
  27.                 }
  28.         }
  29.         if (dis[b] == INF)
  30.                 ans = -1;
  31.         else
  32.                 ans = dis[b];
  33.         if (k)
  34.                 ans = min(ans, dis[(b + n / 2) % n] + 1);
  35.         cout << ans;
  36.         return 0;
  37. }
复制代码

 



E. 平凡DISCO-1


        (1)找树最深的一条链,把其叶子结点作为被换对象
        (2)该条链上每一个点作为父节点,撤消链上的下一个子节点外,其他的子节点作为根节点是的最大深度,找到最大的值,作为被换对象
        (3)son[] 数组里存的是最长链各节点值

  1. #include<bits/stdc++.h>
  2. #define LL long long
  3. using namespace std;
  4. const int N = 5e5 + 5, INF = 0x3f3f3f3f;
  5. int n, ans, dep[N], son[N];
  6. vector<int> G[N];
  7. void dfs(int u, int fa)
  8. {
  9.         dep[u] = 1;
  10.         for (int i = 0; i < G[u].size(); i ++)
  11.         {
  12.                 int v = G[u][i];
  13.                 if (v != fa)
  14.                 {
  15.                         dfs(v, u);
  16.                         dep[u] = max(dep[u], dep[v] + 1);
  17.                         if (dep[v] > dep[son[u]])
  18.                                 son[u] = v;
  19.                 }
  20.         }
  21. }
  22. void add(int u, int fa)
  23. {
  24.         for (int i = 0; i < G[u].size(); i ++)
  25.         {
  26.                 int v = G[u][i];
  27.                 if (v != fa && v != son[u])
  28.                         ans = max(ans, dep[v]);       
  29.         }
  30.         if (son[u])                        // 还没到最长链的叶子结点
  31.                 add(son[u], u);
  32. }
  33. int main()
  34. {
  35.         cin >> n;
  36.         for (int i = 1; i < n; i ++)
  37.         {
  38.                 int u, v;
  39.                 cin >> u >> v;
  40.                 G[u].push_back(v);
  41.                 G[v].push_back(u);
  42.         }
  43.         dfs(1, 0);
  44.         add(1, 0);
  45.         cout << dep[1] + max(ans - 1, 0);
  46.         return 0;
  47. }
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表