方格取數加強版[網路流]
阿新 • • 發佈:2018-12-02
luogu的第一篇題解
#include<bits/stdc++.h> #define N 5000 #define M N*4 #define inf 0x3fffffff using namespace std; int Map[N],n,k,st,ed,dis[N],vis[N],from[M],froms[M]; int first[M],next[M],to[M],w[M],v[M],tot=1; void add(int x,int y,int z,int q){ // cout<<"From "<<x<<" To "<<y<<" with the flow of "<<z<<" and the cost of "<<q<<endl; next[++tot]=first[x],first[x]=tot,to[tot]=y,w[tot]=z,v[tot]=q; next[++tot]=first[y],first[y]=tot,to[tot]=x,w[tot]=0,v[tot]=-q; } bool spfa(){ memset(dis,127,sizeof(dis)); int Inf=dis[0]; memset(vis,0,sizeof(vis)); queue<int> q; dis[st]=0 , vis[st]=0 , q.push(st); while(!q.empty()){ int x=q.front(); q.pop(); vis[x]=0; for(int i=first[x];i;i=next[i]){ int t=to[i]; if(w[i] && dis[t] > dis[x] + v[i]){ from[t] = x , froms[t] = i; dis[t] = dis[x] + v[i]; if(!vis[t]) q.push(t) , vis[t]=1; } } }return dis[ed]!=Inf; } int calc(){ int now = ed , flow=inf; while(now != st){ flow = min(flow , w[froms[now]]); now = from[now]; } now = ed; while(now !=st){ w[froms[now]] -= flow; w[froms[now]^1] += flow; now = from[now]; }return flow; } int dinic(){ int ans=0; while(spfa()){ if(dis[ed]==0) break; ans += calc() * dis[ed]; }return ans; } int main(){ scanf("%d%d",&n,&k); st=0 , ed=n*n*2+1; add(0,1,k,0); add(n*n*2,ed,k,0); for(int i=0;i<n;i++) for(int j=1;j<=n;j++) scanf("%d",&Map[i*n+j]); for(int i=1;i<=n*n;i++){ add(i,i+n*n,1,-Map[i]); add(i,i+n*n,inf,0); } for(int i=0;i<n;i++){ for(int j=1;j<=n;j++){ int pos=i*n+j; if(j<n) add(pos+n*n,pos+1,inf,0); if(i<n-1) add(pos+n*n,pos+n,inf,0); } } printf("%d",-dinic()); return 0; }