zoukankan      html  css  js  c++  java
  • 4.13 省选模拟赛 *组织 bitset 强连通分量 分块

    avatar
    avatar

    考试的时候昏了头 没算空间 这道题我爆零了。值得注意的是 一般认为bitset的空间是 int 的1/w倍

    对于那m条边 无论如何构造 这m条关系都是存在的 题目其实是想让我们用这m条关系来计算给出的 t条关系是否合法。

    合法把这m条边输出即可。

    这道题 虽然不是多组数据 但是评测时开了subtask. 果然 判定对错的题目 基本上不给水分的机会...

    缩过点之后 剩下的是可达性问题 这是一个经典问题 如果点不是类似于区间性的问题 最快也只能使用bitset来解决 这个大概是常识吧.

    发现 mn/w 勉强可以卡过 但是会爆空间。

    这种问题 算是很常见的问题 如 求5,6维偏序的时候 bitset空间容易爆 一般采用根号分治法。

    对n个点进行分块 每次统计一个 块内的点对应的询问即可。

    设 块大小为 S 那么数量为 n/S 每次统计一下 n/SmS/w=nm/w.

    空间复杂度 nS/w.

    可以发现 时间不会变得更差 空间变小 取S等于sqrt(n)即可。

    const int MAXN=100005;
    int n,m,Q,len,top,id,cnt;
    int s[MAXN],c[MAXN],low[MAXN],dfn[MAXN];
    int lin[MAXN],ver[MAXN],nex[MAXN],ru[MAXN];
    int lin1[MAXN],ver1[MAXN],nex1[MAXN];
    bitset<430>b[MAXN];
    int q[MAXN],w[MAXN];
    struct wy{int x,y;}t[MAXN],g[MAXN];
    inline void add(int x,int y)
    {
    	ver[++len]=y;
    	nex[len]=lin[x];
    	lin[x]=len;
    }
    inline void add1(int x,int y)
    {
    	ver1[++len]=y;
    	nex1[len]=lin1[x];
    	lin1[x]=len;
    	++w[y];
    }
    inline void dfs(int x)
    {
    	s[++top]=x;low[x]=dfn[x]=++cnt;
    	go(x)
    	{
    		if(!dfn[tn])
    		{
    			dfs(tn);
    			low[x]=min(low[x],low[tn]);
    		}
    		else if(!c[tn])low[x]=min(low[x],dfn[tn]);
    	}
    	if(dfn[x]==low[x])
    	{
    		int y=0;
    		++id;
    		while(y!=x)
    		{
    			y=s[top--];
    			c[y]=id;
    		}
    	}
    }
    inline void topsort()
    {
    	int l=0,r=0;
    	rep(1,id,i){if(!ru[i])q[++r]=i;}
    	while(++l<=r)
    	{
    		int x=q[l];
    		for(int i=lin1[x];i;i=nex1[i])
    		{
    			int tn=ver1[i];
    			b[tn]=b[tn]|b[x];
    			--ru[tn];
    			if(!ru[tn])q[++r]=tn;
    		}
    	}
    }
    inline int cmp(wy a,wy b){return a.y<b.y;}
    int main()
    {
    	freopen("gplt.in","r",stdin);
    	freopen("gplt.out","w",stdout);
    	get(n);get(m);
    	rep(1,m,i)
    	{
    		int x,y;
    		get(x);get(y);
    		t[i]=(wy){x,y};
    		add(x,y);
    	}
    	rep(1,n,i)if(!dfn[i])dfs(i);
    	len=0;
    	rep(1,n,j)
    	{
    		go(j)
    		{
    			if(c[tn]==c[j])continue;
    			add1(c[tn],c[j]);
    		}
    	}
    	int B=(int)sqrt(1.0*id)+1;
    	int ww=(id-1)/B+1;
    	get(Q);
    	rep(1,Q,i)
    	{
    		int get(x);int get(y); 	
    		x=c[x];y=c[y];
    		g[i]=(wy){x,y};
    	}
    	sort(g+1,g+1+Q,cmp);
    	int flag=1;
    	rep(1,ww,i)
    	{
    		int L=(i-1)*B+1;
    		int R=min(id,i*B);
    		rep(L,R,j)b[j][j-L]=1;
    		topsort();
    		while(g[flag].y<=R&&flag<=Q)
    		{
    			if(b[g[flag].x][g[flag].y-L]==1)
    			{
    				puts("NO");
    				return 0;
    			}
    			++flag;
    		}
    		if(flag==Q+1)break;
    		rep(1,id,j)b[j].reset(),ru[j]=w[j];
    	}
    	puts("YES");
    	put(m);
    	rep(1,m,i)printf("%d %d
    ",t[i].x,t[i].y);
    	return 0;
    }
    

    没脑子选手丢人了。

  • 相关阅读:
    update(十)
    perl-basic-数据类型&引用
    R-barplot()
    leetcode-22-string
    Java-basic-7-面向对象
    Java-basic-6-方法
    Java-basic-4-数据类型
    Java-basic-3-运算符-修饰符-循环
    Java-basic-2-
    leetcode-21-knapsack
  • 原文地址:https://www.cnblogs.com/chdy/p/12691114.html
Copyright © 2011-2022 走看看