#include<iostream>
#include<algorithm>
#include<queue>
#include<memory.h>
#include<string>
using namespace std;
const int N=100005,M=360010,INF=14514191;
int S=100001,T=100002;
int h[N],e[M],f[M],ne[M],idx;
int d[N],cur[N];
int n,m,k;
int id(int x,int y){
if(n>m)return (x-1)*n+y;
else return x+(y-1)*m;
}
void add(int a,int b,int c){
e[idx]=b,f[idx]=c,ne[idx]=h[a],h[a]=idx++;
e[idx]=a,f[idx]=0,ne[idx]=h[b],h[b]=idx++;
}
bool bfs(){
memset(d,-1,sizeof d);
queue<int>q;
q.push(S);
d[S]=0;cur[S]=h[S];
while(!q.empty()){
int t=q.front();q.pop();
for(int i=h[t];~i;i=ne[i]){
int to=e[i];
if(d[to]==-1&&f[i]){
d[to]=d[t]+1;
cur[to]=h[to];
if(to==T)return 1;
q.push(to);
}
}
}
return 0;
}
int find(int u,int limit){
if(u==T)return limit;
int flow=0;
for (int i=cur[u];~i&&flow<limit;i=ne[i]){
cur[u]=i;
int to=e[i];
if(d[to]==d[u]+1&&f[i]){
int t=find(to,min(f[i],limit-flow));
if(!t)d[to]=-1;
f[i]-=t,f[i^1]+=t,flow+=t;
}
}
return flow;
}
int dinic(){
int r=0,flow;
while(bfs()){
cout<<"ok"<<endl;
while(flow=find(S,INF))r+=flow;
}
return r;
}
void work(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int v;
scanf("%d",&v);
add(id(i,j)+n*m,id(i,j),v);
//虚点入边
if(i>1)add(id(i-1,j),id(i,j)+n*m,INF);
if(j>1)add(id(i,j-1),id(i,j)+n*m,INF);
if(i<n)add(id(i+1,j),id(i,j)+n*m,INF);
if(j<m)add(id(i,j+1),id(i,j)+n*m,INF);
//实点出边
if(i>1)add(id(i,j),id(i-1,j),INF);
if(j>1)add(id(i,j),id(i,j-1),INF);
if(i<n)add(id(i,j),id(i+1,j),INF);
if(j<m)add(id(i,j),id(i,j+1),INF);
}
}
for(int i=1;i<=k;i++){
int x,y;
scanf("%d%d",&x,&y);
add(S,id(x,y)+n*m,INF);
}
for(int i=1;i<=k;i++){
int x,y;
scanf("%d%d",&x,&y);
add(id(x,y),T,INF);
}
printf("%d\n",dinic());
}
signed main(){
work();
}
在出网络流题,结果发现std死循环。
具体题面:入点连 k 个节点,另外 k 个节点连出点,不能让入点连到出点,删点的代价为 vi,j,求最小代价。