zoukankan      html  css  js  c++  java
  • [费用流]luogu P3159 交换棋子

    https://www.luogu.org/problemnew/show/P3159

    分析

    这题更神仙

    看到点有出入限制,我们考虑拆点

    但既然从棋盘某点入,就要从棋盘某点出

    所以一个点被拆成了三个,in,mid,out,其中mid连接源汇

    然后从s到初始图的1点连条边,目标图的1点向t连条边,流量均为1

    然后再给每个点向其八联通连边,费用为1,流量为1

    这时候问题来了,我们发现一个点与源点相连时,它参与交换的次数为1,与汇点相连时同样,但是作为交换的中间点,它们参与交换的次数为2

    那我们考虑给流量/2,但是这样问题又出现了,如果它与汇点相连,那么进入的次数要+1,同源点相连时类似

    所以我们给流量除时,考虑给原流量加上1再除(当且仅当与汇点相连)

    此题如此神仙,实是妙哉!

    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <memory.h>
    using namespace std;
    const int N=21;
    const int Inf=2147483647;
    struct Pipe {
        int v,c,w,nx;
    }g[500*N*N];
    int cnt=1,list[3*N*N];
    int dis[3*N*N],f[3*N*N];
    bool vis[3*N*N];
    int n,m,s,t,ans,w,need;
    char a[N][N],b[N][N];
    
    void Add(int u,int v,int c,int w) {
        g[++cnt]=(Pipe){v,c,w,list[u]};list[u]=cnt;
        g[++cnt]=(Pipe){u,0,-w,list[v]};list[v]=cnt;
    }
    
    bool SPFA() {
        queue<int> q;
        while (!q.empty()) q.pop();
        memset(vis,0,sizeof vis);memset(dis,0x3f,sizeof dis);
        q.push(s);vis[s]=1;dis[s]=0;
        while (!q.empty()) {
            int u=q.front();q.pop();
            for (int i=list[u];i;i=g[i].nx)
                if (g[i].c&&dis[g[i].v]>dis[u]+g[i].w) {
                    dis[g[i].v]=dis[u]+g[i].w;f[g[i].v]=i;
                    if (!vis[g[i].v]) q.push(g[i].v);
                    vis[g[i].v]=1;
                }
            vis[u]=0;
        }
        return dis[t]!=0x3f3f3f3f;
    }
    
    void MCF() {
        int x=t,mf=Inf;
        while (f[x]) {
            mf=min(mf,g[f[x]].c);
            x=g[f[x]^1].v;
        }
        x=t;ans+=dis[t];
        while (f[x]) {
            g[f[x]].c-=mf;g[f[x]^1].c+=mf;
            x=g[f[x]^1].v;
        }
    }
    
    void Dinic() {
        while (SPFA()) MCF();
    }
    
    
    int main() {
        scanf("%d%d",&n,&m);s=0;t=3*n*m+1;
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++) 
                do {
                    scanf("%c",&a[i][j]);
                }
                while (a[i][j]!='0'&&a[i][j]!='1');
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++) {
                do {
                    scanf("%c",&b[i][j]);
                }
                while (b[i][j]!='0'&&b[i][j]!='1');
                a[i][j]-=48;b[i][j]-=48;
                if (a[i][j]) Add(s,2*n*m+(i-1)*m+j,1,0),w++;
                if (b[i][j]) Add(2*n*m+(i-1)*m+j,t,1,0),need++;
            }
        if (w!=need) {
            printf("-1");
            return 0;
        }
        need=0;
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++) {
                char c;
                do {
                    scanf("%c",&c);
                }
                while ('0'>c||c>'9');
                c-=48;
                if (c) {
                    Add((i-1)*m+j,2*n*m+(i-1)*m+j,(c+(b[i][j]>a[i][j]))/2,0);
                    Add(2*n*m+(i-1)*m+j,n*m+(i-1)*m+j,(c+(a[i][j]>b[i][j]))/2,0);
                }
            }
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++) {
                if (i>1) {
                    Add(n*m+(i-2)*m+j,(i-1)*m+j,Inf,1);
                    if (j>1) Add(n*m+(i-2)*m+j-1,(i-1)*m+j,Inf,1);
                    if (j<m) Add(n*m+(i-2)*m+j+1,(i-1)*m+j,Inf,1);
                }
                if (i<n) {
                    Add(n*m+i*m+j,(i-1)*m+j,Inf,1);
                    if (j>1) Add(n*m+i*m+j-1,(i-1)*m+j,Inf,1);
                    if (j<m) Add(n*m+i*m+j+1,(i-1)*m+j,Inf,1);
                }
                if (j>1) Add(n*m+(i-1)*m+j-1,(i-1)*m+j,Inf,1);
                if (j<m) Add(n*m+(i-1)*m+j+1,(i-1)*m+j,Inf,1);
            }
        Dinic();
        for (int i=list[t];i;i=g[i].nx)
            if (!g[i].c) {
                printf("-1");
                return 0;
            }
        printf("%d",ans);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    观察者模式
    模版方法
    event
    设计模式之观察者模式
    BOM
    javascript基础语法&4
    Document Object Model
    javascript基础语法&3
    javaScript基础语法&1
    sublimeText3安装
  • 原文地址:https://www.cnblogs.com/mastervan/p/11149086.html
Copyright © 2011-2022 走看看