dls实在是太强啦
可能是我姿势不够高
自己瞎弄弄出个 带下界带正环最大费用循环流
先加超级源汇SS和TT 去下界 转成 带正环最大费用最大流
然后再加超超级源汇S和T 跑一边最大费用最大流 消掉正环
正环没了后 再在SS和TT上跑最大费用最大流
嗯 费用流练习题
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int N=3005;
const int M=1000005;
struct edge{
int u,v,w,f,next;
}G[M];
int head[N],inum=1;
inline void add(int u,int v,int w,int f,int p){
G[p].u=u; G[p].v=v; G[p].w=w; G[p].f=f; G[p].next=head[u]; head[u]=p;
}
inline void link(int u,int v,int w,int f){
add(u,v,w,f,++inum),add(v,u,-w,0,++inum);
}
int S,T,SS,TT;
int dis[N],pre[N],ins[N];
int Q[10000005],l,r;
#define U G[p].u
#define V G[p].v
int Maxcost;
int clk,tag[M];
inline void Link(int u,int v,int w,int f){
if (w<=0)
link(u,v,w,f);
else
Maxcost+=w*f,link(S,v,0,f),link(u,T,0,f),link(v,u,-w,f),tag[inum]=tag[inum-1]=clk;
}
inline bool SPFA(){
for (int i=1;i<=T;i++) dis[i]=-1<<30,pre[i]=0,ins[i]=0;
l=r=-1; Q[++r]=S; dis[S]=0; ins[S]=1;
while (l<r){
int u=Q[++l]; ins[u]=0;
for (int p=head[u];p;p=G[p].next)
if (G[p].f && dis[V]<dis[u]+G[p].w){
dis[V]=dis[u]+G[p].w; pre[V]=p;
if (!ins[V]) Q[++r]=V,ins[V]=1;
}
}
if (dis[T]==-1<<30) return 0;
int minv=1<<30;
for (int p=pre[T];p;p=pre[G[p].u])
minv=min(minv,G[p].f);
Maxcost+=minv*dis[T];
for (int p=pre[T];p;p=pre[G[p].u])
G[p].f-=minv,G[p^1].f+=minv;
return 1;
}
int n,m;
#define I(x,y) (((x)-1)*m+(y))
#define P(x,y,z) ((2*I(x,y))-(1-(z)))
int vst[305][305];
int main(){
int _T,K,x,y,Case=0;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(_T);
while (_T--){
++clk; Maxcost=0;
printf("Case #%d: ",++Case);
read(n); read(m);
SS=2*n*m+1; TT=2*n*m+2; S=2*n*m+3; T=2*n*m+4;
for (int i=1;i<=n;i++)
for (int j=1;j<m;j++){
read(x);
if ((i+j)&1)
Link(P(i,j,0),P(i,j+1,0),x,1);
else
Link(P(i,j+1,0),P(i,j,0),x,1);
}
for (int i=1;i<n;i++)
for (int j=1;j<=m;j++){
read(x);
if (~(i+j)&1)
Link(P(i,j,1),P(i+1,j,1),x,1);
else
Link(P(i+1,j,1),P(i,j,1),x,1);
}
for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) vst[i][j]=0;
read(K); while (K--) read(x),read(y),vst[x][y]=1;
int cnt=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++){
int t=(i+j)&1;
if (!vst[i][j])
Link(P(i,j,t),P(i,j,t^1),0,1);
else
cnt++,Link(SS,P(i,j,t^1),0,1),Link(P(i,j,t),TT,0,1);
}
while (SPFA());
for (int i=1;i<=T;i++) head[i]=0; int tmp=inum;
for (int p=2;p<=tmp;p++)
if (U!=S && U!=T && V!=S && V!=T)
if (tag[p]!=clk)
add(U,V,G[p].w,G[p].f,++inum);
else{
add(V,U,-G[p].w,G[p^1].f,++inum);
}
S=SS; T=TT;
while (SPFA()) cnt--;
if (cnt)
printf("Impossible\n");
else
printf("%d\n",Maxcost);
for (int i=1;i<=T;i++) head[i]=0; inum=1;
}
return 0;
}