• 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

    题解Here!
    这是本蒟蒻见过的强制在线最厉害题。。。
    差点死于强制在线的处理方式。。。
    由于删边不好维护。
    所以将平面图转化为对偶图。
    这样在平面图上删边相当于在对偶图上加边,在平面图上是否联通转化为在对偶图上是否不连通。
    这个就类似于平面图的最大流转化为对偶图的最短路。
    然后用并查集维护一下就好。
    我的强制在线比较骚。。。
    附代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define MAXN 2010
    using namespace std;
    int n,m,q,size;
    int fa[MAXN*MAXN];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    int solve(int x,int y,int f){
    	int u,v;
    	if(f==1){
    		if(x==1){u=y;v=size;}
    		else if(x==n){u=(m-1)*m+y;v=size;}
    		else{u=(x-2)*m+y;v=(x-1)*m+y;}
    	}
    	else{
    		if(y==1){u=(x-1)*m+1;v=size;}
    		else if(y==n){u=x*m;v=size;}
    		else{u=(x-1)*m+y-1;v=(x-1)*m+y;}
    	}
    	u=find(u);v=find(v);
    	if(u==v)return 0;
    	fa[u]=v;
    	return 1;
    }
    void work(){
    	char ch[2];
    	int x,y,last=1;
    	while(q--){
    		x=read();y=read();scanf("%s",ch);
    		if(!last){x=read();y=read();scanf("%s",ch);}
    		int s=solve(x,y,(ch[0]=='N'?1:2));
    		if(last){x=read();y=read();scanf("%s",ch);}
    		last=s;
    		if(s)printf("TAK
    ");
    		else printf("NIE
    ");
    	}
    }
    void init(){
    	n=read();q=read();
    	m=n-1;
    	size=m*m+1;
    	for(int i=1;i<=size;i++)fa[i]=i;
    }
    int main(){
    	init();
    	work();
        return 0;
    }
    
  • 相关阅读:
    巴洛克式和哥特式的区别
    推荐阅读书籍,是时候再行动起来了。
    AtCoder ABC 159F Knapsack for All Segments
    AtCoder ABC 159E Dividing Chocolate
    AtCoder ABC 158F Removing Robots
    AtCoder ABC 158E Divisible Substring
    AtCoder ABC 157F Yakiniku Optimization Problem
    AtCoder ABC 157E Simple String Queries
    AtCoder ABC 157D Friend Suggestions
    AtCoder ABC 156F Modularness
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9557763.html
Copyright © 2020-2023  润新知