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
直接做不好做,考虑转化问题
引进一个网络流的东西:对偶图 这篇博客讲的还是很清晰的
对偶图有个性质:对偶图里的环与原图的割边是相通的
按照这个性质,每次删边就在对偶图上加边,如果加上这条边有环那对应的边就是割边
就是不连通的了,并查集跑跑就OK
代码如下:
//MT_LI
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
    int f=1,x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int stack[20];
inline void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(!x){putchar('0');return;}
    int top=0;
    while(x)stack[++top]=x%10,x/=10;
    while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(int x){write(x);putchar('\n');}
int fa[3100000];
int findfa(int x)
{
    if(fa[x]!=x)fa[x]=findfa(fa[x]);
    return fa[x];
}
int main()
{
    bool bk=true;
    int n=read(),k=read();
    int m=(n-1)*(n-1)+1;
    for(int i=1;i<=m;i++)fa[i]=i;
    while(k--)
    {
        char c1,c2;
        int x=read(),y=read();scanf("%c",&c1);
        int xx=read(),yy=read();scanf("%c",&c2);
        if(!bk)swap(x,xx),swap(y,yy),swap(c1,c2);
        if(c1=='E')
        {
            int fx=findfa((min(x,n-1)-1)*(n-1)+min(n-1,y));int fy;
            if(y==1||y==n)fy=findfa(m);
            else fy=findfa((min(x,n-1)-1)*(n-1)+min(n-1,y-1));
            if(fx==fy){printf("NIE\n");bk=false;}
            else {printf("TAK\n");bk=true;fa[fx]=fy;}
        }
        else
        {
            int fx=findfa((min(x,n-1)-1)*(n-1)+min(n-1,y));int fy;
            if(x==1||x==n)fy=findfa(m);
            else fy=findfa((min(x-1,n-1)-1)*(n-1)+min(n-1,y));
            if(fx==fy){printf("NIE\n");bk=false;}
            else {printf("TAK\n");bk=true;fa[fx]=fy;}
        }
    }
    return 0;
}

 

posted @ 2019-02-12 20:49  MT_LI  阅读(191)  评论(0编辑  收藏  举报