bzoj 5329 [SDOI2018] 战略游戏

bzoj 5329 [SDOI2018] 战略游戏

Link

Solution

很容易想到虚树

然后发现是一个图。。。

现学圆方树,套上去,做完了(模板题?)

就是直接上广义圆方树先把这玩意转换成一棵树,然后对当前询问建立虚树,断掉虚树里任何一个点都合法(包括不出现的点,指那些在某个点和其虚树上父亲之间的点),统计一下即可

Code

// Copyright lzt
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<iostream>
#include<queue>
#include<string>
#include<ctime>
using namespace std;
typedef long long ll;
typedef std::pair<int, int> pii;
typedef long double ld;
typedef unsigned long long ull;
typedef std::pair<long long, long long> pll;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define rep(i, j, k)  for (register int i = (int)(j); i <= (int)(k); i++)
#define rrep(i, j, k) for (register int i = (int)(j); i >= (int)(k); i--)
#define Debug(...) fprintf(stderr, __VA_ARGS__)

inline ll read() {
  ll x = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch <= '9' && ch >= '0') {
    x = 10 * x + ch - '0';
    ch = getchar();
  }
  return x * f;
}

const int maxn = 200200;
int tc, n, m, Q, tot, tim;
int dfn[maxn], low[maxn], S[maxn], s[maxn], q[maxn];
int fa[maxn], dep[maxn], dis[maxn], sz[maxn], son[maxn], top[maxn];

struct Graph {
  int head[maxn], to[maxn << 1], nxt[maxn << 1], tot;
  void init() {
    memset(head, 0, sizeof(head));
    tot = 0;
  }
  void addedge(int x, int y) {
    to[++tot] = y; nxt[tot] = head[x]; head[x] = tot;
    to[++tot] = x; nxt[tot] = head[y]; head[y] = tot;
  }
} G1, G2;

void Tarjan(int u) {
  tim++; dfn[u] = low[u] = tim; S[++S[0]] = u;
  for (int i = G1.head[u]; i; i = G1.nxt[i]) {
    int v = G1.to[i];
    if (!dfn[v]) {
      Tarjan(v); low[u] = min(low[u], low[v]);
      if (low[v] >= dfn[u]) { // 单独一条边连接两个点也得算作点双
        G2.addedge(++tot, u); int x = 0;
        do {
          x = S[S[0]]; S[0]--;
          G2.addedge(tot, x);
        } while (x != v);
      }
    }
    else low[u] = min(low[u], dfn[v]);
  }
}

void dfs1(int u, int pa) {
  fa[u] = pa; dep[u] = dep[pa] + 1; dis[u] = dis[pa] + (u <= n); sz[u] = 1;
  for (int i = G2.head[u]; i; i = G2.nxt[i]) {
    int v = G2.to[i];
    if (v == pa) continue;
    dfs1(v, u); sz[u] += sz[v];
    if (sz[v] > sz[son[u]]) son[u] = v;
  }
}

void dfs2(int u, int tp) {
  top[u] = tp; dfn[u] = ++tim;
  if (son[u]) dfs2(son[u], tp);
  for (int i = G2.head[u]; i; i = G2.nxt[i]) {
    int v = G2.to[i];
    if (v == fa[u] || v == son[u]) continue;
    dfs2(v, v);
  }
  low[u] = tim;
}

int lca(int x, int y) {
  while (top[x] != top[y]) {
    if (dep[top[x]] < dep[top[y]]) swap(x, y);
    x = fa[top[x]];
  }
  return dep[x] < dep[y] ? x : y;
}

bool cmp(int x, int y) {
  return dfn[x] < dfn[y];
}

void work() {
  tc = read();
  while (tc--) {
    n = read(), m = read(); G1.init(); G2.init(); tim = 0; tot = n;
    rep(i, 1, m) {
      int x = read(), y = read();
      G1.addedge(x, y);
    }
    memset(dfn, 0, sizeof(dfn));
    memset(son, 0, sizeof(son));
    rep(i, 1, n) if (!dfn[i]) Tarjan(i);
    tim = 0; dfs1(1, 0); dfs2(1, 1);
    Q = read();
    while (Q--) {
      int k = read(), len = k, tp = 0, ans = 0;
      rep(i, 1, k) s[i] = read();
      sort(s + 1, s + k + 1, cmp);
      rep(i, 1, k - 1) s[++len] = lca(s[i], s[i + 1]);
      sort(s + 1, s + len + 1, cmp);
      len = unique(s + 1, s + len + 1) - (s + 1);
      ans = s[1] <= n;
      rep(i, 1, len) {
        while (tp && low[q[tp]] < dfn[s[i]]) tp--;
        if (tp) ans += dis[s[i]] - dis[q[tp]];
        q[++tp] = s[i];
      }
      printf("%d\n", ans - k);
    }
  }
}

int main() {
  #ifdef LZT
  freopen("in", "r", stdin);
  // freopen("out", "w", stdout);
  #endif

  work();

  #ifdef LZT
  Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
  #endif
}

Review

第一次写圆方树

如果知道圆方树的话这题感觉很好想

原文地址:https://www.cnblogs.com/wawawa8/p/10162887.html

时间: 2024-12-12 20:59:50

bzoj 5329 [SDOI2018] 战略游戏的相关文章

[SDOI2018]战略游戏 圆方树,树链剖分

[SDOI2018]战略游戏 这题是道路相遇(题解)的升级版,询问的两个点变成了\(S\)个点. LG传送门 还是先建出圆方树,考虑对于询问的\(S\)个点,答案就是圆方树上能包含这些点的最小连通块中的圆点个数减去\(S\).问题变成了怎样求这样的连通块中的圆点个数,直接给结论吧:先搞出树的dfs序,把询问的点按dfs序从小到大排一遍序,每次把答案加上第\(i\)和第\(i + 1\)个点之间的圆点个数,但是不算lca,再加上第\(1\)个和第\(S\)个点之间的圆点个数,然后除以二就得到了这个

[SDOI2018]战略游戏

题目描述 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战略游戏的地图由n个城市以及m条连接这些城市的双向道路构成,并且从任意一个城市出发总能沿着道路走到 任意其他城市.现在小C已经占领了其中至少两个城市,小Q可以摧毁一个小C没占领的城市,同时摧毁所有连接这 个城市的道路.只要在摧毁这个城市之后能够找到某两个小C占领的城市u和v,使得从u出发沿着道路无论如何都不 能走到v,那么小Q就能赢下这一局游戏. 小Q和小C一共进行了q局游戏,每一局游戏会给出小C占领

[bzoj5329][Sdoi2018]战略游戏

题目大意:多组数据,每组数据给一张图,多组询问,每个询问给一个点集,要求删除一个点,使得至少点集中的两个点互不连通,输出方案数 题解:圆方树,发现使得两个点不连通的方案数就是它们路径上的原点个数.如何处理重复?可以按圆方树的$dfn$序排序,相邻两点求一下贡献,这样贡献就被重复计算了两次,除去$k$个询问点就行了.还有每次计算中$lca$没有被统计,发现排序后第一个点和最后一个点的$lca$一定是深度最浅的,所以只有这个点没有被统计答案,加上即可 卡点:1.圆方树$dfn$数组没赋值 2.$LC

bzoj3924 [Zjoi2015]幻想乡战略游戏 点分树,动态点分

[BZOJ3924][Zjoi2015]幻想乡战略游戏 Description 傲娇少女幽香正在玩一个非常有趣的战略类游戏,本来这个游戏的地图其实还不算太大,幽香还能管得过来,但是不知道为什么现在的网游厂商把游戏的地图越做越大,以至于幽香一眼根本看不过来,更别说和别人打仗了. 在打仗之前,幽香现在面临一个非常基本的管理问题需要解决. 整个地图是一个树结构,一共有n块空地,这些空地被n-1条带权边连接起来,使得每两个点之间有一条唯一的路径将它们连接起来.在游戏中,幽香可能在空地上增加或者减少一些军

BZOJ 2756 奇怪的游戏(最大流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2756 题意:在一个 N*M 的棋盘上玩,每个格子有一个数.每次 选择两个相邻的格子,并使这两个数都加上 1. 问最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成同一个数则输出-1. 思路:对棋盘进行黑白染色,则每次操作使得黑白两色的格子总和各增加1.设黑色总和s1,个数cnt1:白色总和s2,个数cnt2,设最后的数字为x,那么有: x*cnt1-s1=x*cnt2-s2. (

BZOJ 1413 取石子游戏(DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1413 题意:n堆石子排成一排.每次只能在两侧的两堆中选择一堆拿.至少拿一个.谁不能操作谁输. 思路:参考这里. int f1[N][N],f2[N][N],n,a[N]; void deal() { RD(n); int i,j,k; FOR1(i,n) RD(a[i]),f1[i][i]=f2[i][i]=a[i]; int p,q,x; for(k=2;k<=n;k++) for(

BZOJ 1978 取数游戏(DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1978 题意:给出一个数列a,在其中找出下标依次增大的数,使得任意相邻的两个数的最大公约数大于等于m.找出最多的数字. 思路:f[i]表示前面的数字中最大公约数为i可以找出的最多的数字个数.那么对于当前数字x: 接着更新f: int f[N],a[N]; int n,m; int main() { RD(n,m); int i; FOR1(i,n) RD(a[i]); int j,k;

Facebook开源游戏平台ELF: 一个用于实时战略游戏研究的轻量级平台

ELF是一个用于游戏研究的应用广泛的(Extensive).轻量级的(Lightweight).灵活的(Flexible)平台,特别适用于实时战略(RTS)游戏.在C++方面,ELF采用C++线程来并发运行多个游戏.在Python方面,ELF可以一次性返回一批游戏状态,使其对现代RL(强化学习)非常友好.另一方面,在其他平台(例如OpenAI Gym)中,一个Python接口只能包含一个游戏实例.这使得游戏的并发运行有点复杂,而这又是许多现代强化学习算法的要求. 对于RTS游戏的研究,ELF配备

bzoj 1059: [ZJOI2007]矩阵游戏 二分图匹配

1059: [ZJOI2007]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1891  Solved: 919[Submit][Status] Description 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏.矩阵游戏在一个N*N黑白方阵进行(如同国际象棋一般,只是颜色是随意的).每次可以对该矩阵进行两种操作:行交换操作:选择矩阵的任意两行,交换这两行(即交换对应格子的颜色)列交换操作:选择矩阵