1 条题解

  • 0
    @ 2025-8-24 21:39:29

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar AubRain
    **

    搬运于2025-08-24 21:39:29,当前版本为作者最后更新于2018-11-27 16:54:48,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    其实这题根本没有其它题解说的那么复杂。

    建图方式:

    1、原点向所有狼连流量 infinf 的边

    2、所有羊向汇点连流量 infinf 的边

    3、所有点向四周连流量为 11 的边。

    然后下面就没了。

    求出最小割就是答案,不用考虑题解说的什么 00 的归属问题。

    为什么是对的?

    所有狼和羊之间的边都被割掉了,相当于修了栅栏,所以是对的。

    死因:n,m写反调了一个小时

    #include<bits/stdc++.h>
    #define N 100005
    #define INF 1<<29
    #define num(i,j) ((i-1)*m+j)
    using namespace std;
    
    inline void rd(int &X){
        X=0;int w=0;char ch=0;
        while(!isdigit(ch))w|=ch=='-',ch=getchar();
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        X=w?-X:X;
    }
    
    int n,m,s,t,ans,f,k;
    int head[N],cnt=1,d[N];
    struct nd{int nxt,to,v;}e[N<<1];
    #define For(x) for(int y,i=head[x];(y=e[i].to);i=e[i].nxt)
    
    void add(int x,int y,int w){
        e[++cnt]=(nd){head[x],y,w};head[x]=cnt;
        e[++cnt]=(nd){head[y],x,0};head[y]=cnt;
    }
    bool bfs()
    {
        queue<int> q; q.push(s);
        memset(d,0,sizeof d); d[s]=1;
        while(!q.empty()){
            int x=q.front();q.pop();
            For(x) if(e[i].v&&!d[y]){
                q.push(y); d[y]=d[x]+1;
                if(y==t) return 1;
            }
        } return 0;
    }
    
    int dinic(int x,int flow)
    {
        if(x==t) return flow; int re=flow;
    
        for(int y,i=head[x];(y=e[i].to)&&re;i=e[i].nxt)
            if(e[i].v&&d[y]==d[x]+1)
            {
                k=dinic(y,min(re,e[i].v));
                if(!k) d[y]=0;
                e[i].v-=k;e[i^1].v+=k;re-=k; 
            }
        return flow-re;
    }
    int a[105][105];
    int mx[]={1,-1,0,0};
    int my[]={0,0,1,-1};
    void build()
    {
        rd(n);rd(m);s=n*m+1;t=n*m+2;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                rd(a[i][j]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(a[i][j]==1)
                    add(s,num(i,j),INF);
                else if(a[i][j]==2)
                    add(num(i,j),t,INF);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                for(int k=0;k<4;k++)	
                {
                    int tx=i+mx[k];
                    int ty=j+my[k];
                    if(tx<=n and ty<=m and tx>=1 and ty>=1)
                        add(num(i,j),num(tx,ty),1);
                }
    }
    int main()
    {
        build();
        while(bfs())
            while(f=dinic(s,INF))
                ans+=f;
        cout<<ans;
    }
    
    • 1

    信息

    ID
    1634
    时间
    1000ms
    内存
    125MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者