zoukankan      html  css  js  c++  java
  • HDU2460-Network

    题目

    给一个(n)个点(m)条边的无向连通图,(Q)次往图中加边,每次加边后问图中的桥有多少个。(加边后边留着)。

    (nle 10^5,mle 2 imes 10^5,Qle 10^5)

    分析

    容易发现一条边为桥当且仅当它不在任意一个环中。

    于是我们对最开始的图先得到它的生成树,然后把剩下的边加进去,加边的时候把树上两点路径上的点都标记为不是桥。每次询问的时候一样操作。这个东西可以方便地用树链剖分和线段树维护。

    时间复杂度为(O((m-n+Q)log ^2n))

    代码

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
    #define M(x) memset(x,0,sizeof x)
    using namespace std;
    int read() {
    	int x=0,f=1;
    	char c=getchar();
    	for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
    	for (;isdigit(c);c=getchar()) x=x*10+c-'0';
    	return x*f;
    }
    const int maxn=1e5+1;
    const int maxj=17;
    const int maxm=2e5+1;
    typedef pair<int,int> Pair;
    Pair bian[maxm];
    int n,m;
    namespace uns {
    	int f[maxn];
    	void clear(int n) {for (int i=1;i<=n;++i) f[i]=i;}
    	int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
    }
    namespace sgt {
    	int t[maxn<<2];
    	bool clr[maxn<<2];
    	void init(int x,int l,int r) {
    		clr[x]=false;
    		if (l==r) {
    			t[x]=(l!=1);
    			return;
    		}
    		int mid=(l+r)>>1;
    		init(x<<1,l,mid),init(x<<1|1,mid+1,r);
    		t[x]=t[x<<1]+t[x<<1|1];
    	}
    	void pushdown(int x) {
    		if (!clr[x]) return;
    		t[x<<1]=t[x<<1|1]=0;
    		clr[x<<1]=clr[x<<1|1]=true;
    		clr[x]=false;
    	}
    	void clear(int x,int L,int R,int l,int r) {
    		if (L==l && R==r) {
    			t[x]=0;
    			clr[x]=true;
    			return;
    		}
    		pushdown(x);
    		int mid=(L+R)>>1;
    		if (r<=mid) clear(x<<1,L,mid,l,r); else 
    		if (l>mid) clear(x<<1|1,mid+1,R,l,r); else 
    		clear(x<<1,L,mid,l,mid),clear(x<<1|1,mid+1,R,mid+1,r);
    		t[x]=t[x<<1]+t[x<<1|1];
    	}
    	void clear(int l,int r) {
    		clear(1,1,n,l,r);
    	}
    }
    namespace tree {
    	vector<int> g[maxn];
    	int f[maxn][maxj],dep[maxn],size[maxn],top[maxn],son[maxn];
    	int first[maxn],second[maxn],dfx;
    	void add(int x,int y) {g[x].push_back(y);}
    	void clear(int n) {
    		M(f),M(dep),M(size),M(top),M(son),M(first),M(second),dfx=0;
    		for (int i=1;i<=n;++i) g[i].clear();
    	}
    	int dfs(int x,int fa) {
    		f[x][0]=fa;
    		dep[x]=dep[fa]+1;
    		int &sz=size[x]=1,&sn=son[x]=0;
    		for (int v:g[x]) if (v!=fa) {
    			sz+=dfs(v,x);
    			if (size[v]>size[sn]) sn=v;
    		}
    	}
    	void Top(int x,int fa,int tp) {
    		first[x]=++dfx;
    		top[x]=tp;
    		if (son[x]) Top(son[x],x,tp);
    		for (int v:g[x]) if (v!=son[x] && v!=fa) Top(v,x,v);
    		second[x]=dfx;
    	}
    	void run() {
    		for (int j=1;j<maxj;++j) for (int i=1;i<=n;++i) f[i][j]=f[f[i][j-1]][j-1];
    	}
    	int lca(int x,int y) {
    		if (dep[x]<dep[y]) swap(x,y);
    		for (int j=maxj-1;j>=0;--j) if (dep[f[x][j]]>=dep[y]) x=f[x][j];
    		if (x==y) return x;
    		for (int j=maxj-1;j>=0;--j) if (f[x][j]!=f[y][j]) x=f[x][j],y=f[y][j];
    		return f[x][0];
    	}
    	void work(int x,int l) {
    		for (int y=top[x];dep[y]>dep[l];y=top[x=f[y][0]]) {
    			sgt::clear(first[y],first[x]);
    		}
    		if (dep[x]>dep[l]) sgt::clear(first[l]+1,first[x]);
    	}
    	int deal(int x,int y) {
    		if (dep[x]>dep[y]) swap(x,y);
    		int l=lca(x,y);
    		x==l?work(y,x):work(x,l),work(y,l);
    		return sgt::t[1];
    	}
    }
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("test.in","r",stdin);
    #endif
    	int cases=0;
    	while (true) {
    		n=read(),m=read();
    		if (!n && !m) break;
    		printf("Case %d:
    ",++cases);
    		int wat=0;
    		uns::clear(n);
    		tree::clear(n);
    		for (int i=1;i<=m;++i) {
    			int x=read(),y=read();
    			int fx=uns::find(x),fy=uns::find(y);
    			if (fx!=fy) tree::add(x,y),tree::add(y,x),uns::f[fx]=fy; else bian[++wat]=make_pair(x,y);
    		}
    		tree::dfs(1,1);
    		tree::Top(1,1,1);
    		tree::run();
    		sgt::init(1,1,n);
    		for (int i=1;i<=wat;++i) {
    			int x=bian[i].first,y=bian[i].second;
    			tree::deal(x,y);
    		}
    		int q=read();
    		while (q--) {
    			int x=read(),y=read();
    			int ans=tree::deal(x,y);
    			printf("%d
    ",ans);
    		}
    		puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    9.11 eventbus
    9.10,,,实现new instanceof apply call 高阶函数,偏函数,柯里化
    9.9 promise实现 写完了传到gitee上面了,这里这个不完整
    9.5cors配置代码
    9.5 jsonp 实现
    9.5 http tcp https总结
    9.3 es6 class一部分 and es5 class 发布订阅
    8.30 cookie session token jwt
    8.30vue响应式原理
    warning: LF will be replaced by CRLF in renard-wx/project.config.json. The file will have its original line endings in your working directory
  • 原文地址:https://www.cnblogs.com/owenyu/p/7172118.html
Copyright © 2011-2022 走看看