• [BZOJ3331][BeiJing2013]压力


    description

    给你一张(n)(m)条边的无向图,有(q)组询问形如((u,v)),表示要从(u)走到(v)
    现在问你对于每个点,有多少组询问必经过这个点。

    sol

    一张图中两个点之间的必经点就是圆方树上两点路径上的所有圆点。
    所以只要树上差分一波就可以了。

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int gi(){
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 4e5+5;
    int n,tot,m,q,dfn[N],low[N],tim,S[N];
    int fa[N],dep[N],sz[N],son[N],top[N],val[N];
    struct Graph{
    	int to[N],nxt[N],head[N],cnt;
    	void link(int u,int v){
    		to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
    		to[++cnt]=u;nxt[cnt]=head[v];head[v]=cnt;
    	}
    }G1,G2;
    void Tarjan(int u){
    	dfn[u]=low[u]=++tim;S[++S[0]]=u;
    	for (int e=G1.head[u];e;e=G1.nxt[e]){
    		int v=G1.to[e];
    		if (!dfn[v]){
    			Tarjan(v),low[u]=min(low[u],low[v]);
    			if (low[v]>=dfn[u]){
    				G2.link(++tot,u);int x=0;
    				do{
    					x=S[S[0]--];G2.link(tot,x);
    				}while (x!=v);
    			}
    		}
    		else low[u]=min(low[u],dfn[v]);
    	}
    }
    void dfs1(int u,int f){
    	fa[u]=f;dep[u]=dep[f]+1;sz[u]=1;
    	for (int e=G2.head[u];e;e=G2.nxt[e]){
    		int v=G2.to[e];if (v==f) continue;
    		dfs1(v,u);sz[u]+=sz[v];
    		if (sz[v]>sz[son[u]]) son[u]=v;
    	}
    }
    void dfs2(int u,int up){
    	top[u]=up;
    	if (son[u]) dfs2(son[u],up);
    	for (int e=G2.head[u];e;e=G2.nxt[e]){
    		int v=G2.to[e];if (v==fa[u]||v==son[u]) continue;
    		dfs2(v,v);
    	}
    }
    int getlca(int u,int v){
    	while (top[u]^top[v]){
    		if (dep[top[u]]<dep[top[v]]) swap(u,v);
    		u=fa[top[u]];
    	}
    	return dep[u]<dep[v]?u:v;
    }
    void dfs(int u){
    	for (int e=G2.head[u];e;e=G2.nxt[e]){
    		int v=G2.to[e];if (v==fa[u]) continue;
    		dfs(v);val[u]+=val[v];
    	}
    }
    int main(){
    	tot=n=gi();m=gi();q=gi();
    	while (m--){
    		int u=gi(),v=gi();
    		G1.link(u,v);
    	}
    	for (int i=1;i<=n;++i) if (!dfn[i]) Tarjan(i);
    	dfs1(1,0),dfs2(1,1);
    	while (q--){
    		int u=gi(),v=gi(),gg=getlca(u,v);
    		++val[u];++val[v];--val[gg];--val[fa[gg]];
    	}
    	dfs(1);
    	for (int i=1;i<=n;++i) printf("%d
    ",val[i]);
    	return 0;
    }
    
  • 相关阅读:
    开博说两句
    学习总结 (持续更新)
    ip代理 120203
    [vs2005]关于预编绎网站的问题[已预编译此应用程序的错误]
    JAVA类基础
    集合类和泛型
    IO流——字符流
    多线程和包
    多态和内部类
    抽象类与接口
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9088480.html
Copyright © 2020-2023  润新知