• 【BZOJ4423】[AMPPZ2013]Bytehattan 对偶图+并查集


    【BZOJ4423】[AMPPZ2013]Bytehattan

    Description

    比特哈顿镇有n*n个格点,形成了一个网格图。一开始整张图是完整的。
    有k次操作,每次会删掉图中的一条边(u,v),你需要回答在删除这条边之后u和v是否仍然连通。

    Input

    第一行包含两个正整数n,k(2<=n<=1500,1<=k<=2n(n-1)),表示网格图的大小以及操作的个数。
    接下来k行,每行包含两条信息,每条信息包含两个正整数a,b(1<=a,b<=n)以及一个字符c(c=N或者E)。
    如果c=N,表示删除(a,b)到(a,b+1)这条边;如果c=E,表示删除(a,b)到(a+1,b)这条边。
    数据进行了加密,对于每个操作,如果上一个询问回答为TAK或者这是第一个操作,那么只考虑第一条信息,否则只考虑第二条信息。
    数据保证每条边最多被删除一次。

    Output

    输出k行,对于每个询问,如果仍然连通,输出TAK,否则输出NIE。

    Sample Input

    3 4
    2 1 E 1 2 N
    2 1 N 1 1 N
    3 1 N 2 1 N
    2 2 N 1 1 N

    Sample Output

    TAK
    TAK
    NIE
    NIE

    题解:乍一看是离线+并查集,但这题偏偏强制在线

    想到因为是网格图,可以用对偶图优化一下,将网格中的交点看成点,每加入一条边就相当于连接两个点,这个可以用并查集来搞

    然后在连接两个点之前,判断一下这两个点是否在一个连通块内,如果这两个点在一个连通块里,说明两点间已经有一条路径相连,则再连接这条边之后必定会构成一个环,就说明那条边两侧的方格被隔开了

    注意要先把所有网格边界上的点全连上

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    int n,m,ans;
    int f[1502*1502];
    char c[5],cc[5];
    int find(int x)
    {
    	return (f[x]==x)?x:(f[x]=find(f[x]));
    }
    int main()
    {
    	scanf("%d%d",&n,&m),n++;
    	int a,b,i,aa,bb,ra,rb;
    	for(i=1;i<=n*n;i++)	f[i]=(i<=n||i>n*n-n||i%n==1||i%n==0)?1:i;
    	for(i=1;i<=m;i++)
    	{
    		scanf("%d%d%s%d%d%s",&a,&b,c,&aa,&bb,cc);
    		if(ans)	a=aa,b=bb,c[0]=cc[0];
    		aa=find(a*n+b+1);
    		if(c[0]=='E')	bb=find(a*n+b);
    		if(c[0]=='N')	bb=find((a-1)*n+b+1);
    		if(find(aa)==find(bb))
    		{
    			printf("NIE
    ");
    			ans=1;
    		}
    		else
    		{
    			f[f[aa]]=f[bb];
    			printf("TAK
    ");
    			ans=0;
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    Canvas 3D球形文字云动画特效
    CSS3实现各种表情
    使用html+css+js实现弹球游戏
    CSS3实现图片木桶布局
    JQ实现弹幕效果
    css实现导航切换
    使用JS实现俄罗斯方块游戏
    JS实现文本中查找并替换字符
    Qt笔记之 01主函数和配置文件详解
    C++学习笔记之 异常
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6530104.html
Copyright © 2020-2023  润新知