【Bitset】友好城市

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34454069/article/details/88735973

在这里插入图片描述


分析:

分块+st表+bitset卡常

把公路分成k块,内部通过bitset处理出连通状况。

每次询问,把连续的一些块通过st表得到边,再用两次dfs求强连通分量的方法,合并这些边,得到新的连通状况。

#include<cstdio>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<bitset>
#include<vector>
#define SF scanf
#define PF printf
#define MAXM 300010
#define MAXN 160
#define MAXB 800
using namespace std;
const int k=400;
pair<int,int> l[MAXM];
bitset<MAXN> f1[MAXB][12][MAXN],f0[MAXB][12][MAXN],tmp0[MAXN];
bitset<MAXN> f3[MAXB][12][MAXN],f2[MAXB][12][MAXN],tmp1[MAXN];
bitset<MAXN> vis;
int stk[MAXN],top;
void dfs1(int x){
	vis[x]=0;
	bitset<MAXN> now=vis&tmp0[x];
	while(now.any()){
		int pos=now._Find_next(0);
		dfs1(pos);
		now=vis&tmp0[x];
	}
	stk[++top]=x;
}
int dfs2(int x){
	vis[x]=0;
	bitset<MAXN> now=vis&tmp1[x];
	int res=1;
	while(now.any()){
		int pos=now._Find_next(0);
		res+=dfs2(pos);
		now=vis&tmp1[x];
	}
	return res;
}
int n,m,q;
int query(){
	top=0;
	for(int i=1;i<=n;i++)
		vis[i]=1;
	for(int i=1;i<=n;i++)
		if(vis[i]==1)
			dfs1(i);
	for(int i=1;i<=n;i++)
		vis[i]=1;
	int res=0;
	for(int i=n;i>=1;i--)
		if(vis[stk[i]]==1){
			int siz=dfs2(stk[i]);
			res+=siz*(siz-1)/2;
		}
	return res;
}
void ins(int L,int R,int id){
	int l1=(id-1)*k;
	int r1=id*k-1;
	L=max(l1,L);
	R=min(r1,R);
	for(int i=L;i<=R;i++){
		tmp0[l[i].first][l[i].second]=1;
		tmp1[l[i].second][l[i].first]=1;
	}
}
int blo[MAXM],maxf[MAXB];
int main(){
	freopen("friend.in","r",stdin);
	freopen("friend.out","w",stdout);
	SF("%d%d%d",&n,&m,&q);
	for(int i=1;i<=m;i++){
		SF("%d%d",&l[i].first,&l[i].second);
		blo[i]=i/k+1;
	}
	int tot=m/k+1;
	for(int i=1;i<=m;i++){
		f0[blo[i]][0][l[i].first][l[i].second]=1;
		f1[blo[i]][0][l[i].first][l[i].second]=1;
		f2[blo[i]][0][l[i].second][l[i].first]=1;
		f3[blo[i]][0][l[i].second][l[i].first]=1;
	}
	for(int i=1;i<=tot;i++)
		for(int j=1;(1<<j)<=i;j++)
			maxf[i]=j;
	for(int i=1;i<11;i++)
		for(int j=1;j<=tot;j++)
			for(int l=1;l<=n;l++){
				f0[j][i][l]=f0[j][i-1][l]|f0[min(tot,j+(1<<(i-1)))][i-1][l];
				f2[j][i][l]=f2[j][i-1][l]|f2[min(tot,j+(1<<(i-1)))][i-1][l];
			}
	for(int i=1;i<11;i++)
		for(int j=tot;j>=1;j--)
			for(int l=1;l<=n;l++){
				f1[j][i][l]=f1[j][i-1][l]|f1[max(1,j-(1<<(i-1)))][i-1][l];
				f3[j][i][l]=f3[j][i-1][l]|f3[max(1,j-(1<<(i-1)))][i-1][l];
			}
	int L,R;
	for(int i=1;i<=q;i++){
		SF("%d%d",&L,&R);
		int L1=blo[L];
		int R1=blo[R];
		for(int j=1;j<=n;j++) tmp0[j].reset(),tmp1[j].reset();
		ins(L,R,L1);
		ins(L,R,R1);
		L1++;
		R1--;
		if(L1<=R1){
			int dis=R1-L1+1;
			for(int j=1;j<=n;j++){
				tmp0[j]|=f0[L1][maxf[dis]][j]|f1[R1][maxf[dis]][j];
				tmp1[j]|=f2[L1][maxf[dis]][j]|f3[R1][maxf[dis]][j];
			}
		}
		PF("%lld\n",query());
	}
}

猜你喜欢

转载自blog.csdn.net/qq_34454069/article/details/88735973