Luogu T29912 fuck

这是QZEZ的Luogu团队中的一道难得的水题,题面和数据都是CJJ dalao出的,然后我就没有太看懂题意。

也是一道经典的割点好题,但需要一定的思维

首先对于题意,它只需要得到切断的作用就可以了(将(1)的联通快分成几部分即可)

然后我们就可以对周围的点都进行建边,然后跑一下看看有没有割点

有的话很明显,随便找一个割点一道切掉即可。但如果没有呢?

据CJJ dalao和我的一阵讨论发现这时候就只需要割掉两个点即可。

例如类似这样的一个图:

1 1 1

1 0 1

1 1 1

我们在割去一边上的任意一个点时就会出现割点。不知道是什么性质。

然后莫名就过了。

CODE

#include<cstdio>
#include<cctype>
#include<cstring>
using namespace std;
const int N=305,fx[4]={0,1,0,-1},fy[4]={1,0,-1,0};
struct edge
{
    int to,next;
}e[N*N<<3];
int head[N*N],father[N*N],low[N*N],dfn[N*N],cnt,tot,ans,t,n,m,g[N][N];
bool cut[N*N];
inline char tc(void)
{
    static char fl[100000],*A=fl,*B=fl;
    return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
    x=0; char ch; while (!isdigit(ch=tc()));
    while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
}
inline void add(int x,int y)
{
    e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt;
}
inline int min(int a,int b)
{
    return a<b?a:b;
}
inline void clear(void)
{
    memset(e,-1,sizeof(e)); memset(head,-1,sizeof(head));
    memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn));
    memset(father,0,sizeof(father)); memset(cut,0,sizeof(cut)); cnt=ans=0;
}
inline void build(int x,int y)
{
    for (register int i=0;i<4;++i)
    {
        int xx=x+fx[i],yy=y+fy[i];
        if (xx>0&&yy>0&&xx<=n&&yy<=m&&g[xx][yy]) add((x-1)*m+y,(xx-1)*m+yy);
    }
}
inline void Tarjan(int now)
{
    dfn[now]=low[now]=++tot; int res=0;
    for (register int i=head[now];i!=-1;i=e[i].next)
    if (!dfn[e[i].to])
    {
        father[e[i].to]=now; ++res; 
        Tarjan(e[i].to); low[now]=min(low[now],low[e[i].to]);
        if (father[now]&&low[e[i].to]>=dfn[now]) !cut[now]&&(cut[now]=1,++ans);
    } else if (e[i].to!=father[now]) low[now]=min(low[now],dfn[e[i].to]);
    if (!father[now]&&res>=2) !cut[now]&&(cut[now]=1,++ans);
}
int main()
{
    //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    register int i,j; read(t);
    while (t--)
    {
        clear(); read(n); read(m);
        for (i=1;i<=n;++i)
        for (j=1;j<=m;++j)
        read(g[i][j]);
        for (i=1;i<=n;++i)
        for (j=1;j<=m;++j)
        if (g[i][j]) build(i,j);
        for (i=1;i<=n*m;++i)
        if (!dfn[i]) Tarjan(i);
        puts(ans?"1":"2");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/cjjsb/p/9276576.html