我在每个点双里 bfs 为什么会t啊
查看原帖
我在每个点双里 bfs 为什么会t啊
176843
LiveZoom楼主2023/8/4 23:05

代码:

#include <cassert>
#include <cstdio>
#include <iostream>
#include <queue>
#include <stack>
#include <tuple>
#include <vector>

// #define int int64_t

using i64 = int64_t;

const int kMaxN = 1e6 + 5;

int n, m, t, cnt;
i64 ans;
int dfn[kMaxN], low[kMaxN], col[kMaxN], ss[kMaxN], fa[kMaxN], sz[kMaxN], q[kMaxN];
bool in[kMaxN], vis[kMaxN];
std::vector<int> T[kMaxN];
std::vector<std::tuple<int, int, int>> G[kMaxN];

int find(int x) {
  return x == fa[x] ? x : fa[x] = find(fa[x]);
}

void unionn(int x, int y) {
  int fx = find(x), fy = find(y);
  if (fx != fy) fa[fx] = fy, sz[fy] += sz[fx];
}

void tarjan(int u, int lst) {
  static int cnt = 0;
  static std::stack<int> stk;
  dfn[u] = low[u] = ++cnt;
  stk.emplace(u);
  for (auto [v, c, id] : G[u]) {
    if (!dfn[v]) {
      tarjan(v, id);
      low[u] = std::min(low[u], low[v]);
      if (low[v] >= dfn[u]) {
        ++t;
        while (!stk.empty()) {
          int k = stk.top();
          stk.pop();
          T[t].emplace_back(k), T[k].emplace_back(t);
          if (k == v) break;
        }
        T[t].emplace_back(u), T[u].emplace_back(t);
      }
    } else if (id != lst) {
      low[u] = std::min(low[u], dfn[v]);
    }
  }
}

void bfs(int id) {
  for (auto x : T[id]) {
    in[x] = 1;
    ss[x] = 0;
  }
  int h = 1, t = 0;
  int s = 0;
  q[++t] = T[id][0], vis[T[id][0]] = 1;
  while (h <= t) {
    int u = q[h++];
    for (auto [v, c, id] : G[u]) {
      if (!in[v]) continue;
      s |= (1 << c), ss[u] |= (1 << c), ss[v] |= (1 << c);
      if (!vis[v]) q[++t] = v, vis[v] = 1;
    }
  }
  int cnt = 0;
  for (auto x : T[id]) {
    in[x] = vis[x] = 0;
    cnt += (ss[x] == 3);
    ss[x] = 0;
  }
  if (cnt == 2) --ans;
  if (s == 3) s = 0;
  else if (s == 0) s = 3;
  col[id] = s;
}

void dickdreamer() {
  std::cin >> n >> m;
  ans = (i64)n * (n - 1) / 2;
  for (int i = 1; i <= m; ++i) {
    int u, v;
    std::string c;
    std::cin >> u >> v >> c;
    G[u].emplace_back(v, c[0] == 'd', i), G[v].emplace_back(u, c[0] == 'd', i);
  }
  t = n;
  for (int i = 1; i <= n; ++i)
    if (!dfn[i])
      tarjan(i, 0);
  // std::cerr << "!!!\n";
  // for (int i = n + 1; i <= t; ++i)
  //   std::cerr << T[i].size() << '\n';
  for (int i = n + 1; i <= t; ++i)
    bfs(i);
  // std::cerr << "???\n";
  for (int i = 1; i <= t; ++i) {
    fa[i] = i;
    sz[i] = (i <= n);
  }
  for (int i = n + 1; i <= t; ++i)
    if (col[i] == 1)
      for (auto j : T[i])
        unionn(i, j);
  for (int i = 1; i <= t; ++i)
    if (find(i) == i)
      ans -= (i64)sz[i] * (sz[i] - 1) / 2;
  for (int i = 1; i <= t; ++i) {
    fa[i] = i;
    sz[i] = (i <= n);
  }
  for (int i = n + 1; i <= t; ++i)
    if (col[i] == 2)
      for (auto j : T[i])
        unionn(i, j);
  for (int i = 1; i <= t; ++i)
    if (find(i) == i)
      ans -= (i64)sz[i] * (sz[i] - 1) / 2;  
  std::cout << ans << '\n';
}

int32_t main() {
#ifdef ORZXKR
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout);
#endif
  std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
  int T = 1, S;
  // std::cin >> T;
  std::cin >> S;
  while (T--) dickdreamer();
  // std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
  return 0;
}

里面的

void bfs(int id) {
  for (auto x : T[id]) {
    in[x] = 1;
    ss[x] = 0;
  }
  int h = 1, t = 0;
  int s = 0;
  q[++t] = T[id][0], vis[T[id][0]] = 1;
  while (h <= t) {
    int u = q[h++];
    for (auto [v, c, id] : G[u]) {
      if (!in[v]) continue;
      s |= (1 << c), ss[u] |= (1 << c), ss[v] |= (1 << c);
      if (!vis[v]) q[++t] = v, vis[v] = 1;
    }
  }
  int cnt = 0;
  for (auto x : T[id]) {
    in[x] = vis[x] = 0;
    cnt += (ss[x] == 3);
    ss[x] = 0;
  }
  if (cnt == 2) --ans;
  if (s == 3) s = 0;
  else if (s == 0) s = 3;
  col[id] = s;
}

这个玩意为啥会 T 啊!!!

它不是线性的吗

2023/8/4 23:05
加载中...