首页 > 其他分享 >AT_joisc2016_g ダンジョン2

AT_joisc2016_g ダンジョン2

时间:2024-12-04 18:11:26浏览次数:4  
标签:joisc2016 val int Move fa array dis

不妨先建出一棵 dfs 树,然后给每个点标号。那么现在就是要确定所有非树边的端点。

考虑三进制拆分,第 \(i\) 轮每个点颜色为其第 \(i\) 位的值。

于是可以求出每条非树边终点的第 \(i\) 位。这样只要跑 \(\log_3n\le5\) 次。

不妨把每条非树边挂到较低点求值,实现可以考虑定义颜色 \(3\) 为已回溯,\(2\) 为访问且未回溯,\(1\) 为未访问。每次判断两端颜色都为 \(2\) 即可。

于是这样 Move 次数为 \(4m+5\times 2\times m=14m\) 次,可以通过。

#include "dungeon2.h"
#include <bits/stdc++.h>
#define ALL(x) begin(x), end(x)
using namespace std;
using ll = long long;

const int kN = 205;
const vector<int> pw3 {1, 3, 9, 27, 81};
int n;
array<int, kN> ans, deg;
array<bool, kN> vis;
array<array<int, kN>, kN> dis;
array<vector<int>, kN> to, val;

void build(int x, int fa) {
  int fa_edge = LastRoad();
  deg[x] = NumberOfRoads();
  to[x] = val[x] = vector<int> (deg[x] + 1, 0);
  if(x != 1) to[x][fa_edge] = -fa;
  for(int i = 1; i <= deg[x]; i++) {
    if(i == fa_edge) continue;
    Move(i, 2);
    if(Color() == 1) {
      n++, to[x][i] = -n;
      dis[x][n] = dis[n][x] = 1;
      build(n, x);
    }else {
      if(Color() == 3) {
        to[x][i] = -kN;
      }
      Move(LastRoad(), 2);
    }
  }
  if(x != 1) Move(fa_edge, 3);
}

void find(int x, int w) {
  int fa_edge = LastRoad();
  if(x == 1) fa_edge = -1;
  int col = x / pw3[w] % 3 + 1;
  for(int i = 1; i <= deg[x]; i++) {
    if(i == fa_edge) continue;
    if((to[x][i] < 0) && (to[x][i] != -kN)) {
      Move(i, col);
      find(-to[x][i], w);
    }
  }
  for(int i = 1; i <= deg[x]; i++) {
    if((to[x][i] >= 0) && (val[x][i] == -1)) {
      Move(i, col);
      val[x][i] = Color() - 1;
      Move(LastRoad(), Color());
    }
  }
  if(x != 1) Move(fa_edge, col);
}

void Inspect(int R) {
  const int kInf = 1e9;
  for(auto& k : dis) k.fill(kInf);
  for(int i = 0; i < kN; i++) {
    dis[i][i] = 0;
  }

  build(n = 1, 0);
  for(int i = 0; i < 5; i++) {
    for(int j = 1; j <= n; j++) {
      fill(ALL(val[j]), -1);
    }
    find(1, i);
    for(int j = 1; j <= n; j++) {
      for(int k = 1; k <= deg[j]; k++) {
        if(to[j][k] >= 0) {
          to[j][k] += pw3[i] * val[j][k];
        }
      }
    }
  }
  for(int i = 1; i <= n; i++) {
    for(int j = 1; j <= deg[i]; j++) {
      if(to[i][j] >= 0) {
        int id = to[i][j];
        dis[i][id] = dis[id][i] = 1;
      }
    }
  }

  for(int i = 1; i <= n; i++) {
    for(int j = 1; j <= n; j++) {
      for(int k = 1; k <= n; k++) {
        dis[j][k] = min(dis[j][k], dis[j][i] + dis[i][k]);
      }
    }
  }
  for(int i = 1; i <= n; i++) {
    for(int j = i + 1; j <= n; j++) {
      ans[dis[i][j]]++;
    }
  }
  for(int i = 1; i <= R; i++) {
    Answer(i, ans[i]);
  }
}

标签:joisc2016,val,int,Move,fa,array,dis
From: https://www.cnblogs.com/cjoierzdc/p/18586900

相关文章

  • JOISC2016 题解
    仍然是没有做通信题。JOISC2016Day1Matryoshka俄罗斯套娃转化错了,转化成上升子序列了,然后就变成了区间LIS。实际上是LDS,那么就可以直接做了。https://qoj.ac/submission/99648JOISC2016Day1Memory2神经衰弱我们对数进行两两配对,然后把每一对都问出来。如果不存在相......