方格取数加强版

努力刷网络流找感觉ing……


 这其实是一个费用流,拆点,流量为1,费用为val。

求其最大费用流,可以转化为边权相反,求最小费用流的相反数。

看代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
int val[100][100];
int n,k;
const int maxn=1e5+10;
int beg[maxn],nex[maxn],to[maxn],w[maxn],f[maxn],e;
inline void add(int x,int y,int z,int c){
    nex[e]=beg[x];beg[x]=e;
    to[e]=y;w[e]=c;f[e]=z;e++;
}
int flow[maxn],dis[maxn],vis[maxn];
queue<int>q;
int las[maxn],pos[maxn];
inline int spfa(){
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    while(!q.empty())q.pop();
    dis[0]=0;
    flow[0]=inf;
    vis[0]=1;
    q.push(0);
    while(!q.empty()){
        int x=q.front();
        q.pop();
        vis[x]=0;
        for(int i=beg[x];~i;i=nex[i]){
            int t=to[i];
            if(f[i]&&dis[t]>dis[x]+w[i]){
                dis[t]=dis[x]+w[i];
                las[t]=x;
                pos[t]=i;
                flow[t]=min(flow[x],f[i]);
                if(!vis[t]){
                    vis[t]=1;
                    q.push(t);
                }
            }
        }
    }
    return dis[2*n*n+1]<=1000000;
}
int main(){
    memset(beg,-1,sizeof(beg));
    cin>>n>>k;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            cin>>val[i][j];
    add(0,1,k,0);
    add(1,0,0,0);
    add(2*n*n,2*n*n+1,k,0);
    add(2*n*n+1,2*n*n,0,0);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            add((i-1)*n+j,(i-1)*n+j+n*n,1,-val[i][j]);
            add((i-1)*n+j+n*n,(i-1)*n+j,0,val[i][j]);
            add((i-1)*n+j,(i-1)*n+j+n*n,inf,0);
            add((i-1)*n+j+n*n,(i-1)*n+j,0,0);
            if(i<n){
                add((i-1)*n+j+n*n,i*n+j,inf,0);
                add(i*n+j,(i-1)*n+j+n*n,0,0);
            }
            if(j<n){
                add((i-1)*n+j+n*n,(i-1)*n+j+1,inf,0);
                add((i-1)*n+j+1,(i-1)*n+j+n*n,0,0);
            }
        }
    int ans=0;
    while(spfa()){
        ans-=flow[2*n*n+1]*dis[2*n*n+1];
        int tmp=2*n*n+1;
        while(tmp!=0){
            f[pos[tmp]]-=flow[2*n*n+1];
            f[pos[tmp]^1]+=flow[2*n*n+1];
            tmp=las[tmp];
        }
    }
    printf("%d
",ans);
    return 0;
}

深深地感到自己的弱小。

原文地址:https://www.cnblogs.com/syzf2222/p/12431118.html