zoukankan      html  css  js  c++  java
  • 战略游戏[SDOI2018]

    https://www.luogu.com.cn/problem/P4606

    题解

    每次是试图摧毁一个城市和它连着的所有边,发现如果摧毁的不是一个割点那么就不会有任何影响,所以先建出原图的圆方树

    每次选择了若干个关键节点,建出这些关键节点在圆方树上的虚树,有一个显而易见的结论:

    答案即为虚树上(包括在虚树的某条边上)所有非关键节点的圆点个数

    虚树上所有的叶子节点都一定是关键节点

    断掉一个非关键的圆点一定会使得它子树里的一个叶子节点和其它子树外的关键节点不再连通

    所以断掉一个非关键的圆点一定满足小Q要求

    这题也不需要真的把虚树建出来,预处理圆方树上每个点到根的路径上有多少圆点,查询时只需要统计虚树的每条边上有多少圆点,最后再减掉 (|S|) 个关键圆点即为答案

    #include <bits/stdc++.h>
    #define N 300005
    using namespace std;
    
    template <typename T>
    inline void read(T &num) {
    	T x = 0, ff = 1; char ch = getchar();
    	for (; ch > '9' || ch < '0'; ch = getchar()) if (ch == '-') ff = -1;
    	for (; ch <= '9' && ch >= '0'; ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ '0');
    	num = x * ff; 
    }
    template <typename T>
    void write(T num) {
    	if (num < 0) putchar('-'), num = -num;
    	if (num > 9) write(num/10);
    	putchar(num%10+'0');
    }
    
    int ttt, n, P, m, Q, K;
    int head[N], pre[N<<1], to[N<<1], sz;
    int dfn[N], dfsx[N], low[N], tme, stk[N], top, pp[N]; 
    vector<int> e[N];
    int d[N], p[N][21], sum[N];
    
    void init_TU() { memset(head, 0, sizeof(head)); sz = 0; }
    void init_OTHERS() {
    	for (int i = 1; i <= n; i++) e[i].clear();
    	memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); tme = 0;
    	memset(stk, 0, sizeof(stk)); top = 0; memset(dfsx, 0, sizeof(dfsx));
    	memset(d, 0, sizeof(d)); memset(p, 0, sizeof(p)); memset(sum, 0, sizeof(sum));
    }
    void initALL() { init_TU(); init_OTHERS(); }
    void addedge(int u, int v) {
    	pre[++sz] = head[u]; head[u] = sz; to[sz] = v;
    	pre[++sz] = head[v]; head[v] = sz; to[sz] = u;
    }
    
    void tarjan(int x) {
    	dfn[x] = low[x] = ++tme; stk[++top] = x;
    	for (int i = head[x]; i; i = pre[i]) {
    		int y = to[i];
    		if (!dfn[y]) {
    			tarjan(y);
    			low[x] = min(low[x], low[y]);
    			if (low[y] == dfn[x]) {
    				int z = 0; ++n;
    				do {
    					z = stk[top--];
    					e[z].push_back(n); e[n].push_back(z);
    				} while (z != y);
    				e[x].push_back(n); e[n].push_back(x);
    			}
    		} else low[x] = min(low[x], dfn[y]);
    	}
    }
    
    void dfs(int x, int fa) {
    	dfsx[x] = ++tme; sum[x] = (x <= P) + sum[fa];
    	for (int l = 1; (1 << l) <= n; l++) p[x][l] = p[p[x][l-1]][l-1];
    	for (auto y : e[x]) {
    		if (y == fa) continue;
    		d[y] = d[x] + 1; p[y][0] = x; dfs(y, x);
    	}
    }
    inline int LCA(int x, int y) {
    	if (d[x] < d[y]) swap(x, y);
    	for (int i = 20; ~i; i--) if (d[x]-(1<<i)>=d[y]) x = p[x][i];
    	if (x == y) return x;
    	for (int i = 20; ~i; i--) if (p[x][i] != p[y][i]) x = p[x][i], y = p[y][i];
    	return p[x][0];
    } 
    bool cmp(int x, int y) { return dfsx[x] < dfsx[y]; }
    int solve() {
    	top = 0; int ans = 0;
    	for (int i = 1; i <= K; i++) {
    		if (!top) { stk[++top] = pp[i]; continue; }
    		int lca = LCA(stk[top], pp[i]);
    		while (top > 1 && dfsx[stk[top-1]] >= dfsx[lca]) {
    			ans += sum[stk[top]]-sum[stk[top-1]]; --top;
    		} 
    		if (stk[top] != lca) {
    			ans += sum[stk[top]]-sum[lca]; stk[top] = lca;
    		}
    		stk[++top] = pp[i];
    	}
    	while (top > 1) { 
    		ans += sum[stk[top]]-sum[stk[top-1]]; --top; 
    	}
    	ans += (stk[top] <= P);
    	return ans - K;
    }
    int main() {
    	read(ttt);
    	while (ttt--) {
    		initALL();
    		read(n); read(m); P = n;
    		for (int i = 1, u, v; i <= m; i++) {
    			read(u); read(v); addedge(u, v);
    		}
    		tarjan(1); tme = 0; dfs(1, 0);
    		read(Q);
    		for (int kk = 1; kk <= Q; kk++) {
    			read(K); for (int i = 1; i <= K; i++) read(pp[i]);
    			sort(pp + 1, pp + K + 1, cmp);
    			write(solve()); puts("");
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    正在找工作/打算找工作的看过来!
    xx星空面试题
    买的书不少,看的书不多,这是病
    公司那么多 我想去面面
    Android设备直接运行java项目?还杀不死?
    node-sass安装失败 解决办法(linux和window)
    Vue + element控制鼠标右键菜单
    Vue.js中Promise、异步、同步、定时器
    选择器&伪类选择器
    根据城市名称获取对应的省份名称
  • 原文地址:https://www.cnblogs.com/ak-dream/p/AK_DREAM120.html
Copyright © 2011-2022 走看看