1 条题解

  • 0
    @ 2025-8-24 22:05:28

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 小菜鸟
    咕咕咕(

    搬运于2025-08-24 22:05:28,当前版本为作者最后更新于2019-06-26 21:18:01,作者可能在搬运后再次修改,您可在原文处查看最新版

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

    以下是正文


    上一篇题解还是讲得过于简单了吧...

    稍微详细一点。

    每个点可以向其他点传输能量,显然是网络流。

    同时,不能间接传输能量,

    那么考虑拆点,将一个点拆成入点和出点,点与点之间只有入点能向出点传输能量。

    这样就避免了已经被传输到出点的能量再被传到别处去。

    然后就是套路,源点向第ii个入点连AiA_i的边,第ii个出点向汇点连BiB_i的边,每个入点向对应的出点连inf\inf的边。

    输出方案的话,只要看看每条边上的剩余容量与原来差了多少,就知道起点向终点传输了多少能量了。

    代码可以参考

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using std::queue;
    
    const int N=1005,M=500005;
    
    const int S=1003,T=1004;
    
    int n,m;
    
    int head[N],cur[N],level[N];
    
    struct Edge
    {
        int next,to,w,w0;
    };
    Edge E[M];
    
    void __add(int u,int v,int w)
    {
        static int tot=-1;
        E[++tot].next=head[u];
        E[tot].to=v;
        E[tot].w=E[tot].w0=w;
        head[u]=tot;
    }
    void add(int u,int v,int w)
    {
        __add(u,v,w);
        __add(v,u,0);
    }
    
    bool bfs(int S,int T)
    {
        memset(level,0x00,sizeof(level));
        queue<int> q;
        q.push(S);
        level[S]=1;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=head[u];~i;i=E[i].next)
            {
                int v=E[i].to;
                if(E[i].w==0||level[v]!=0)continue;
                level[v]=level[u]+1;
                q.push(v);
            }
        }
        return level[T];
    }
    
    int dfs(int u,int flow,int T)
    {
        if(u==T||flow==0)return flow;
        int res=0;
        for(int i=cur[u];~i;cur[u]=i=E[i].next)
        {
            int v=E[i].to;
            if(level[v]==level[u]+1&&E[i].w!=0)
            {
                int f=dfs(v,std::min(flow,E[i].w),T);
                if(f!=0)
                {
                    res+=f;
                    flow-=f;
                    E[i].w-=f;
                    E[i^1].w+=f;
                    if(flow==0)break;
                }
            }
        }
        return res;
    }
    
    int dinic(int S,int T)
    {
        int res=0;
        while(bfs(S,T))
        {
            memcpy(cur,head,sizeof(head));
            res+=dfs(S,0x7fffffff,T);
        }
        return res;
    }
    
    int in_id(int x)
    {
        return x;
    }
    
    int out_id(int x)
    {
        return x+n;
    }
    
    int ans[N][N];
    
    int main()
    {
        memset(head,0xff,sizeof(head));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
        {
            int x;
            scanf("%d",&x);
            add(S,in_id(i),x);
            add(in_id(i),out_id(i),0x3fffffff);
        }
        int sum=0;
        for(int i=1;i<=n;++i)
        {
            int x;
            scanf("%d",&x);
            sum+=x;
            add(out_id(i),T,x);
        }
        for(int i=0;i<m;++i)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(in_id(u),out_id(v),0x3fffffff);
            add(in_id(v),out_id(u),0x3fffffff);
        }
        if(dinic(S,T)!=sum)
        {
            puts("NO");
            return 0;
        }
        puts("YES");
        for(int u=1;u<=n;++u)
        {
            for(int i=head[u];~i;i=E[i].next)
            {
                int v=E[i].to;
                if(v<=n)continue;
                if(v>n*2)continue;
                v-=n;
                ans[u][v]+=E[i].w0-E[i].w;
            }
        }
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=n;++j)
            {
                printf("%d ",ans[i][j]);
            }
            putchar('\n');
        }
    }
    
    • 1

    信息

    ID
    3925
    时间
    1000ms
    内存
    250MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者