HDU&icpc15沈阳网络赛I. Stability(双连通缩点+树剖)

还是太年轻了,根本没往双连通想…

由于边双连通缩点后是一棵树,那就缩点吧!!

因为边双连通的边不会对答案有贡献!!(定义可知)

, , 题目有删边操作,那不妨倒序考虑,慢慢加边处理询问

, a , b , a b ? 现在得到了一棵树,对于a,b间的连通性,不就是a到b在树上有多少边吗?

线 这个树剖线段树轻松搞定

? , ? ? 但是加边操作呢?导致这不是一棵树了,又要去缩点??

, a b a b 在纸上画一画,在a-b加边只是让a到b的路径形成一个连通分量

0 只需要把这些边的贡献修改成0就好了

, 至于边权转点权,把边权下放到儿子就好了

#include <bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
const int maxn=1e5+10;
const int MAXN=1e5+10;
const int MAXM=1e5+10;
int n,m,q,u[maxn],v[maxn];
typedef pair<int,int>p;
vector<int>vec[maxn<<1];
map<p,int>mp;
struct edge{
	int u,to,nxt;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v){
	d[++cnt]=(edge){u,v,head[u]},head[u]=cnt;
}
/*缩点部分*/ 
int vistime;
int dfn[MAXN];
int low[MAXN];
int col[MAXN];
int ccnt;
bool isbridge[MAXM];
void tarjan(int u, int fa)
{
    dfn[u] = low[u] = ++vistime;
    for (int i = head[u]; i; i = d[i].nxt)
    {
        int v = d[i].to;
        if (!dfn[v])
        {
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if (low[v] > dfn[u])
                isbridge[i] = isbridge[i ^ 1] = true;
        }
        else if (dfn[v] < dfn[u] && v != fa)
        {
            low[u] = min(low[u], dfn[v]);
        }
    }
}
void sd(int u)
{
    dfn[u] = 1;
    col[u] = ccnt;
    for (int i = head[u]; i; i = d[i].nxt)
    {
        int v = d[i].to;
        if (isbridge[i])
            continue;
        if (!dfn[v])
            sd(v);
    }
}
struct QUERY{
	int type,l,r;
}ask[maxn];
int fa[maxn],deep[maxn],siz[maxn],son[maxn];
void dfs1(int u,int father)
{
	fa[u]=father, deep[u]=deep[father]+1, siz[u]=1;
	for(int i=0;i<vec[u].size();i++)
	{
		int v=vec[u][i];
		if( v==father )	continue;
		dfs1(v,u);
		siz[u]+=siz[v];
		if( siz[son[u]]<siz[v] )	son[u]=v;
	}
}
int id[maxn],top[maxn],dfs_num,idf[maxn];
void dfs2(int u,int topf)
{
	top[u]=topf,id[u]=++dfs_num,idf[dfs_num]=u;
	if( !son[u] )	return;
	dfs2( son[u],topf );
	for(int i=0;i<vec[u].size();i++ )
	{
		int v=vec[u][i];
		if( v==fa[u]||v==son[u] )	continue;
		dfs2(v,v);
	}
}
int a[1000009],laz[1000009];
void push_down(int rt,int len )
{
	if( laz[rt]==-1 )	return;
	laz[rt<<1]=laz[rt], laz[rt<<1|1]=laz[rt];
	a[rt<<1]=laz[rt]*( len-len/2 ), a[rt<<1|1]=laz[rt]*( len/2 );
	laz[rt]=-1;
}
void build(int rt,int l,int r)
{
	laz[rt]=-1,a[rt]=0;
	if( l==r )	{ a[rt]=1; return; }
	build(lson); build(rson);
	a[rt] = a[rt<<1] + a[rt<<1|1];
}
void update(int rt,int l,int r,int L,int R,int k)
{
	if( l>R||r<L )	return;
	if( L<=l&&R>=r )
	{
		laz[rt]=k,a[rt]=( r-l+1 )*k;
		return;
	}
	push_down( rt,r-l+1 );
	update(lson,L,R,k); update(rson,L,R,k);
	push_down( rt,r-l+1 );
	a[rt]=a[rt<<1]+a[rt<<1+1];
}
void update_lian(int x,int y,int z)
{
	while( top[x]!=top[y] )
	{
		if( deep[top[x]]<deep[top[y]] )	swap(x,y);
		update(1,1,ccnt,id[top[x]],id[x],z);
		x=fa[top[x]];
	}
	if( x==y )	return;//相等 
	if( deep[x]>deep[y] )	swap(x,y);
	update(1,1,ccnt,id[son[x]],id[y],z );
}
int query(int rt,int l,int r,int L,int R)
{
	if( l>R||r<L )	return 0;
	if( L<=l&&R>=r )	return a[rt];
	push_down(rt,r-l+1);
	return query(lson,L,R)+query(rson,L,R);
}
int query_lian(int x,int y)
{
	int res=0;
	while( top[x]!=top[y] )
	{
		if( deep[top[x]]<deep[top[y]] )	swap(x,y);
		res+=query(1,1,ccnt,id[top[x]],id[x] );
		x=fa[top[x]];
	}
	if( deep[x]>deep[y] )	swap(x,y);
	if( x!=y )
		res+=query(1,1,ccnt,id[son[x]],id[y] );
	return res;
}
int main()
{
	int casenum=0,T;
	cin >> T;
	while( T-- )
	{
		cnt=1,ccnt=0;
		memset(id,0,sizeof(id));
		memset(head,0,sizeof(head));
		memset(dfn,0,sizeof(dfn));
		memset(low,0,sizeof(low));
		memset(isbridge,0,sizeof(isbridge));
		memset(col,0,sizeof(col));
		memset(son,-1,sizeof(son));
		memset(siz,0,sizeof(siz));
		
		vistime=0;dfs_num=0;
		for(int i=0;i<=200000;i++)	vec[i].clear();
		mp.clear();
		cin >> n >> m >> q;
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d",&u[i],&v[i]);
			if( u[i]>v[i] )	swap(u[i],v[i]);
			mp[p(u[i],v[i])]++;
		}
		for(int i=1;i<=q;i++)
		{
			scanf("%d%d%d",&ask[i].type,&ask[i].l,&ask[i].r);
			if( ask[i].l>ask[i].r )	swap( ask[i].l,ask[i].r );
			if( ask[i].type==2 )	continue;
			mp[ p(ask[i].l,ask[i].r)]--;
		}
		for(int i=1;i<=m;i++)
		{
			p w=(p){ u[i],v[i] };
			if( mp[w]==0 )	continue;
			add(u[i],v[i]); add(v[i],u[i]);
			mp[w]--;
		}
		for(int i=1;i<=n;i++)
			if( !dfn[i] )	tarjan(i,-1);
		memset(dfn,0,sizeof(dfn));
		for(int i=1;i<=n;i++)
			if( !dfn[i] )
				ccnt++,sd(i);
		for(int i=2;i<=cnt;i++)
		{
			int u=d[i].u,v=d[i].to;
			if( col[u]!=col[v] )
				vec[ col[u] ].push_back( col[v] );
		}
		dfs1(1,0);
		dfs2(1,1);
		build(1,1,ccnt);
		vector<int>ans;
		for(int i=q;i>=1;i--)
		{
			int type=ask[i].type,l=ask[i].l,r=ask[i].r;
			if( type==1 )
				update_lian( id[l],id[r],0 );
			else
				ans.push_back( query_lian(id[l],id[r] ) );
		}
		printf("Case #%d:\n", ++casenum);
		for(int i=ans.size()-1;i>=0;i--)
			printf("%d\n",ans[i]);
	}
}

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/108417776