【HDU2460】Network

题目链接:HDU2460

解法:树链剖分

若原图为一棵树,则所有边都是桥。那么先建出一棵原图的生成树。
对于其余的边 ( u , v ) (u,v) (u,v) ,在生成树中找到 u u u v v v 的简单路径,并将路径上的边标记为不是桥。将边的信息转移到点,可以树剖实现。每次修改后查询即可。

代码

#include
#include
#include
#include

using namespace std;

struct edge{
	int u,v;
	edge():u(0),v(0){}
	edge(int x,int y):u(x),v(y){}
};

vector<edge> vec;
vector<int> point[100001];
int t,n,m,q,x,y,f[100001],fa[100001],son[100001],dep[100001],siz[100001],top[100001],dfn[100001],idx,tag[400001],sum[400001];
bool check[200001];

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

bool merge(int x,int y){int fx=find(x),fy=find(y);if(fx==fy)return false;return f[fx]=fy,true;}

void work(){for(int i=0;i<vec.size();++i){edge e=vec[i];int u=e.u,v=e.v;if(!merge(u,v))check[i]=true;else point[u].push_back(v),point[v].push_back(u);}}

inline void pushdown(int o,int l,int r){tag[o<<1]=tag[o<<1|1]=tag[o];int m=l+r>>1;sum[o<<1]=tag[o]*(m-l+1),sum[o<<1|1]=tag[o]*(r-m);tag[o]=0;}

void update(int o,int l,int r,int a,int b,int x){
	if(l==a&&r==b){sum[o]=(tag[o]=x)*(r-l+1);return;}
	if(tag[o])pushdown(o,l,r);
	int m=l+r>>1;if(m>=b)update(o<<1,l,m,a,b,x);else if(m<a)update(o<<1|1,m+1,r,a,b,x);else update(o<<1,l,m,a,m,x),update(o<<1|1,m+1,r,m+1,b,x);
	sum[o]=sum[o<<1]+sum[o<<1|1];
}

int query(int o,int l,int r,int a,int b){
	if(l==a&&r==b)return sum[o];
	if(tag[o])pushdown(o,l,r);
	int m=l+r>>1;if(m>=b)return query(o<<1,l,m,a,b);else if(m<a)return query(o<<1|1,m+1,r,a,b);else return query(o<<1,l,m,a,m)+query(o<<1|1,m+1,r,m+1,b);
}

void dfs1(int u){siz[u]=1;for(int v:point[u])if(v!=fa[u]){dep[v]=dep[fa[v]=u]+1,dfs1(v),siz[u]+=siz[v];if(siz[v]>siz[son[u]])son[u]=v;}}

void dfs2(int u){dfn[u]=++idx;if(son[u])top[son[u]]=top[u],dfs2(son[u]);for(int v:point[u])if(v!=fa[u]&&v!=son[u])top[v]=v,dfs2(v);}

void change(int u,int v){
	while(top[u]!=top[v]){if(dep[top[u]]>dep[top[v]])swap(u,v);update(1,1,n,dfn[top[v]],dfn[v],1),v=fa[top[v]];}
	if(dep[u]>dep[v])swap(u,v);if(dfn[u]<dfn[v])update(1,1,n,dfn[u]+1,dfn[v],1);
}

int main(){
	while(++t){
		vec.clear(),memset(fa,idx=0,sizeof(fa)),memset(dep,0,sizeof(dep)),memset(siz,0,sizeof(siz)),memset(top,0,sizeof(top)),memset(son,0,sizeof(son)),memset(dfn,0,sizeof(dfn)),memset(sum,0,sizeof(sum)),memset(tag,0,sizeof(tag)),memset(check,false,sizeof(check));
		scanf("%d%d",&n,&m);
		if(!n)return 0;for(int i=1;i<=n;++i)point[i].clear(),f[i]=i;
		for(int i=1;i<=m;++i)scanf("%d%d",&x,&y),vec.push_back(edge(x,y));
		work();
		dfs1(1),dfs2(top[1]=1);
		for(int i=0;i<vec.size();++i)if(check[i])change(vec[i].u,vec[i].v);
		scanf("%d",&q);printf("Case %d:\n",t);for(int i=1;i<=q;++i)scanf("%d%d",&x,&y),change(x,y),printf("%d\n",n-sum[1]-1);
	}
}

你可能感兴趣的:(树链剖分)