• 洛谷P4606 [SDOI2018]战略游戏 【圆方树 + 虚树】


    题目链接

    洛谷P4606
    双倍经验:弱化版

    题解

    两点之间必经的点就是圆方树上两点之间的圆点
    所以只需建出圆方树
    每次询问建出虚树,统计一下虚树边上有多少圆点即可
    还要讨论一下经不经过根(1)的情况

    P4606

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cls(s) memset(s,0,sizeof(s))
    #define cp pair<int,int>
    #define LL long long int
    using namespace std;
    const int maxn = 200005,maxm = 100005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    int h[maxn],ne = 1,hh[maxn],Ne = 1;
    struct EDGE{int to,nxt;}ed[maxn << 2],e[maxn << 2];
    inline void build(int u,int v){
    	e[++Ne] = (EDGE){v,hh[u]}; hh[u] = Ne;
    	e[++Ne] = (EDGE){u,hh[v]}; hh[v] = Ne;
    }
    inline void add(int u,int v){
    	ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
    	ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
    }
    int n,m,N,dfn[maxn],low[maxn],st[maxn],top,cnt;
    void dfs(int u,int last){
    	dfn[u] = low[u] = ++cnt;
    	st[++top] = u;
    	for (int k = hh[u],to; k; k = e[k].nxt){
    		if (k == last) continue;
    		if (!dfn[to = e[k].to]){
    			dfs(to,k ^ 1);
    			low[u] = min(low[u],low[to]);
    			if (low[to] >= dfn[u]){
    				++N;
    				do{add(st[top],N);}while (st[top--] != to);
    				add(N,u);
    			}
    		}
    		else low[u] = min(low[u],dfn[to]);
    	}
    }
    int K,a[maxn],fa[maxn][20],d[maxn][20],Dfn[maxn],dep[maxn],dfc;
    void DFS(int u){
    	Dfn[u] = ++dfc; d[u][0] = (u <= n);
    	REP(i,19){
    		fa[u][i] = fa[fa[u][i - 1]][i - 1];
    		d[u][i] = d[u][i - 1] + d[fa[u][i - 1]][i - 1];
    	}
    	Redge(u) if ((to = ed[k].to) != fa[u][0]){
    		fa[to][0] = u; dep[to] = dep[u] + 1; DFS(to);
    	}
    }
    inline int lca(int u,int v){
    	if (dep[u] < dep[v]) swap(u,v);
    	for (int i = 0,D = dep[u] - dep[v]; (1 << i) <= D; i++)
    		if (D & (1 << i)) u = fa[u][i];
    	if (u == v) return u;
    	for (int i = 19; ~i; i--)
    		if (fa[u][i] != fa[v][i]){
    			u = fa[u][i];
    			v = fa[v][i];
    		}
    	return fa[u][0];
    }
    inline int getup(int u,int v){
    	if (u == v) return 0;
    	int re = -(u <= n);
    	for (int i = 19; ~i; i--)
    		if (fa[u][i] && dep[fa[u][i]] >= dep[v]){
    			re += d[u][i];
    			u = fa[u][i];
    		}
    	return re;
    }
    inline bool cmp(const int& a,const int& b){
    	return Dfn[a] < Dfn[b];
    }
    int pre[maxn];
    void work(){
    	st[top = 1] = 1; int tot = 0,M = K;
    	sort(a + 1,a + 1 + K,cmp);
    	for (int i = 1; i <= K; i++){
    		int u = a[i],p = lca(u,st[top]);
    		if (u == 1) tot = INF;
    		if (p == st[top]) {if (u != st[top]) st[++top] = u;}
    		else {
    			while (true){
    				if (dep[p] >= dep[st[top - 1]]){
    					pre[st[top--]] = p; if (p == 1) tot++;
    					if (st[top] != p) st[++top] = p,a[++M] = p;
    					break;
    				}
    				pre[st[top]] = st[top - 1];
    				if (st[top - 1] == 1) tot++;
    				top--;
    			}
    			if (u != st[top]) st[++top] = u;
    		}
    	}
    	while (top > 1){
    		pre[st[top]] = st[top - 1];
    		if (st[top - 1] == 1) tot++;
    		top--;
    	}
    	if (tot < INF) a[++M] = 1;
    	int ans = 0;
    	for (int i = 1; i <= M; i++){
    		int u = a[i];
    		if (u == 1){
    			if (i > K && tot > 1) ans++;
    			continue;
    		}
    		if (pre[u] != 1 || (pre[u] == 1 && tot > 1)) ans += getup(u,pre[u]);
    		if (i > K) ans += (u <= n);
    		pre[u] = 0;
    	}
    	printf("%d
    ",ans);
    }
    int main(){
    	int T = read();
    	while (T--){
    		cls(dfn); cls(h); cls(hh);
    		ne = Ne = 1; cnt = dfc = top = 0;
    		N = n = read(); m = read();
    		REP(i,m) build(read(),read());
    		dfs(1,0); DFS(1);
    		int q = read();
    		while (q--){
    			K = read();
    			REP(i,K) a[i] = read();
    			work();
    		}
    	}
    	return 0;
    }
    
    

    P4320

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cls(s) memset(s,0,sizeof(s))
    #define cp pair<int,int>
    #define LL long long int
    using namespace std;
    const int maxn = 1000005,maxm = 100005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    int h[maxn],ne = 1,hh[maxn],Ne = 1;
    struct EDGE{int to,nxt;}ed[maxn << 2],e[maxn << 2];
    inline void build(int u,int v){
    	e[++Ne] = (EDGE){v,hh[u]}; hh[u] = Ne;
    	e[++Ne] = (EDGE){u,hh[v]}; hh[v] = Ne;
    }
    inline void add(int u,int v){
    	ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
    	ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
    }
    int n,m,N,val[maxn];
    int dfn[maxn],low[maxn],st[maxn],top,cnt;
    void dfs(int u,int last){
    	dfn[u] = low[u] = ++cnt;
    	st[++top] = u;
    	for (int k = hh[u],to; k; k = e[k].nxt){
    		if (k == last) continue;
    		if (!dfn[to = e[k].to]){
    			dfs(to,k ^ 1);
    			low[u] = min(low[u],low[to]);
    			if (low[to] >= dfn[u]){
    				++N;
    				do{add(st[top],N);}while (st[top--] != to);
    				add(N,u);
    			}
    		}
    		else low[u] = min(low[u],dfn[to]);
    	}
    }
    int fa[maxn][20],d[maxn][20],Dfn[maxn],dep[maxn],dfc;
    void DFS(int u){
    	Dfn[u] = ++dfc; d[u][0] = (u <= n);
    	REP(i,19){
    		fa[u][i] = fa[fa[u][i - 1]][i - 1];
    		d[u][i] = d[u][i - 1] + d[fa[u][i - 1]][i - 1];
    	}
    	Redge(u) if ((to = ed[k].to) != fa[u][0]){
    		fa[to][0] = u; dep[to] = dep[u] + 1; DFS(to);
    	}
    }
    int dis(int u,int v){
    	int re = 0;
    	if (dep[u] < dep[v]) swap(u,v);
    	for (int i = 0,D = dep[u] - dep[v]; (1 << i) <= D; i++)
    		if (D & (1 << i)){
    			re += d[u][i];
    			u = fa[u][i];
    		}
    	if (u == v) return re + 1;
    	for (int i = 19; ~i; i--)
    		if (fa[u][i] != fa[v][i]){
    			re += d[u][i] + d[v][i];
    			u = fa[u][i];
    			v = fa[v][i];
    		}
    	re += d[u][0] + d[v][0];
    	if (fa[u][0] <= n) re++;
    	return re;
    }
    int main(){
    	N = n = read(); m = read();
    	REP(i,m) build(read(),read());
    	dfs(1,0);
    	DFS(1);
    	int q = read(),u,v;
    	while (q--){
    		u = read(); v = read();
    		printf("%d
    ",dis(u,v));
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    移步
    使用mingw在windows下搭建c/c++IDE环境
    安全协议系列(一)WEP详解
    碎碎念、我的2013!
    运维常见问题总结
    排序,分页,出现数据重复或缺失
    Terracotta中锁与性能的问题
    【转】Linux系统的性能测试与性能分析
    Distributed Cache Guideline
    脚本大搜罗
  • 原文地址:https://www.cnblogs.com/Mychael/p/9194811.html
Copyright © 2020-2023  润新知