zoukankan      html  css  js  c++  java
  • bzoj#4423-[AMPPZ2013]Bytehattan【并查集】

    正题

    题目链接:https://darkbzoj.tk/problem/4423


    题目大意

    给出一个(n*n)的网格图,然后四联通的点之间连接。每次删掉一条边求这条边的两个点是否连通。强制在线。

    (1leq nleq 1500,1leq mleq 2n(n-1))


    解题思路

    转换成对偶图之后就可以变成加边判断连通性的问题了。

    一个很简单的理解就是如果新的删去的边在对偶图构成了一个环那么就会被分成环内和环外了。

    时间复杂度(O(malpha(m)))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1600;
    int n,k,fa[N*N];
    int find(int x)
    {return (fa[x]==x)?(x):(fa[x]=find(fa[x]));}
    void Unionm(int x,int y){
    	x=find(x);y=find(y);
    	if(x==y)return;fa[x]=y;
    } 
    int main()
    {
    	scanf("%d%d",&n,&k);
    	bool last=1;
    	for(int i=1;i<=(n+1)*(n+1);i++)fa[i]=i;
    	for(int i=1;i<=n;i++){
    		Unionm(i,i+1);
    		Unionm((i-1)*(n+1)+1,i*(n+1)+1);
    		Unionm(n*(n+1)+i,n*(n+1)+i+1);
    		Unionm((i-1)*(n+1)+n+1,i*(n+1)+n+1);
    	}
    	for(int i=1;i<=k;i++){
    		int x1,x2,y1,y2,x,y,p,q;
    		char op1[2],op2[2],op;
    		scanf("%d%d%s",&x1,&y1,&op1);
    		scanf("%d%d%s",&x2,&y2,&op2);
    		if(last)x=x1,y=y1,op=op1[0];
    		else x=x2,y=y2,op=op2[0];
    		if(op=='N'){
    			p=x*(n+1)+y+1;
    			q=(x-1)*(n+1)+y+1;
    			p=find(p);q=find(q);
    			if(p!=q)last=1,puts("TAK");
    			else last=0,puts("NIE");
    		}
    		else{
    			p=x*(n+1)+y+1;
    			q=x*(n+1)+y;
    			p=find(p);q=find(q);
    			if(p!=q)last=1,puts("TAK");
    			else last=0,puts("NIE");
    		}
    		Unionm(p,q);
    	}
    	return 0;
    }
    
  • 相关阅读:
    学习笔记
    js闭包
    一个非必现问题的定位和反思
    C语言的设计模式面向对象机制的实现(一)
    多线程和单线程的执行效率问题
    python 多态
    C语言的设计模式接口隔离
    构建表达式二叉树
    C语言的设计模式依赖倒置
    C语言的设计模式单一职责
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15114453.html
Copyright © 2011-2022 走看看