BJOI 2017 Kakuro
Data Constraint
Code:
#include<bits/stdc++.h> using namespace std; #define MAX 37 #define N (47*47<<2|7) #define M (N<<3|7) #define LL long long #define eho(x) for(int i=head[x];i;i=net[i]) #define v fall[i] #define inf 143323223 #define Min(a,b) (a<b?a:b) //#define int LL struct Lxf{ int S,T,tot,head[N],fall[M],net[M],lim[M],cost[M],la[N],lat[N],dis[N]; LL cs; Lxf() {tot=1;} void Add(int x,int y,int Lim,int Cost){ fall[++tot]=y; net[tot]=head[x]; head[x]=tot; lim[tot]=Lim; cost[tot]=Cost; } void add(int x,int y,int Lim,int Cost){ Add(x,y,Lim,Cost); Add(y,x,0,-Cost); } bool spfa() { static queue<int> Q; static int in[N],x; memset(dis,121,sizeof dis); dis[S]=0; dis[S]=0; in[S]=1; Q.push(S); while (!Q.empty()) { x=Q.front(); Q.pop(); eho(x) if (lim[i]&&dis[x]+cost[i]<dis[v]) { dis[v]=dis[x]+cost[i],la[v]=i,lat[v]=x; if (!in[v]) in[v]=1,Q.push(v); } in[x]=0; } return dis[T]<0; } LL Flow(int s,int t,int &flow) { S=s; T=t; flow=0; cs=0; while (spfa()) { int fl=inf; for (int i=t;i!=s;i=lat[i]) fl=Min(fl,lim[la[i]]); cs+=1ll*fl*dis[T]; flow+=fl; for (int i=t;i!=s;i=lat[i]) lim[la[i]]-=fl,lim[la[i]^1]+=fl; } return cs; } bool check() { for(int i=1;i<=tot;i+=2) { if(cost[i]==inf&&lim[i^1]>0) return 0; if(cost[i]==-inf&&lim[i]>0) return 0; } return 1; } }G; int n,m,Tp[MAX][MAX],IdC[MAX][MAX],Line[MAX][MAX],IdL[MAX][MAX],Ori[MAX][MAX],Column[MAX][MAX],cnt,Left[MAX][MAX],dow; void write(LL x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);} inline void writeln(LL x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('\n'); } inline void writel(LL x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); } LL ans,CO; template <class T> inline void read(T& x){ static char c; static int b; for (c=getchar(),b=1;!isdigit(c);c=getchar()) if (c=='-') b=-1; for (x=0;isdigit(c);c=getchar()) x=x*10+c-48; x*=b; } int ChangeC[MAX][MAX],ChangeL[MAX][MAX],ChangeO[MAX][MAX],Up[MAX][MAX],AfterC[MAX][MAX],AfterL[MAX][MAX],AfterO[MAX][MAX]; signed main () { freopen("kakuro.in","r",stdin); freopen("kakuro.out","w",stdout); read(n); read(m); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) read(Tp[i][j]); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { if(Tp[i][j]==1||Tp[i][j]==3) { read(Column[i][j]); IdC[i][j]=++cnt; } if(Tp[i][j]==2||Tp[i][j]==3) { read(Line[i][j]); IdL[i][j]=++cnt; } if(Tp[i][j]==4) read(Ori[i][j]); } for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { if(Tp[i][j]==1||Tp[i][j]==3) { read(ChangeC[i][j]); if(ChangeC[i][j]==-1) ChangeC[i][j]=inf; } if(Tp[i][j]==2||Tp[i][j]==3) { read(ChangeL[i][j]); if(ChangeL[i][j]==-1) ChangeL[i][j]=inf; } if(Tp[i][j]==4) { read(ChangeO[i][j]); if(ChangeO[i][j]==-1) ChangeO[i][j]=inf; } } for(int i=1;i<=n;i++) for (int j=1;j<=m;j++) { if(Tp[i][j]==1||Tp[i][j]==3) { int k=i+1; while(k<=n&&Tp[k][j]==4) Up[k++][j]=IdC[i][j]; AfterC[i][j]=k-i-1; ans+=1ll*ChangeC[i][j]*abs(AfterC[i][j]-Column[i][j]); } if(Tp[i][j]==2||Tp[i][j]==3) { int k=j+1; while(k<=M&&Tp[i][k]==4) Left[i][k++]=IdL[i][j]; AfterL[i][j]=k-j-1; ans+=1ll*ChangeL[i][j]*abs(AfterL[i][j]-Line[i][j]); } if(Tp[i][j]==4) { AfterO[i][j]=1; ans+=1ll*ChangeO[i][j]*abs(AfterO[i][j]-Ori[i][j]); } } for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { if(Tp[i][j]==1||Tp[i][j]==3) { if(AfterC[i][j] < Column[i][j]) G.add(0,IdC[i][j],Column[i][j]-AfterC[i][j],-ChangeC[i][j]); G.add(0,IdC[i][j],inf,ChangeC[i][j]); } if(Tp[i][j]==2||Tp[i][j]==3) { if(AfterL[i][j] < Line[i][j]) G.add(IdL[i][j],cnt+1,Line[i][j]-AfterL[i][j],-ChangeL[i][j]); G.add(IdL[i][j],cnt+1,inf,ChangeL[i][j]); } if(Tp[i][j]==4) { if(AfterO[i][j]<Ori[i][j]) G.add(Up[i][j],Left[i][j],Ori[i][j]-AfterO[i][j],-ChangeO[i][j]); G.add(Up[i][j],Left[i][j],inf,ChangeO[i][j]); } } CO=G.Flow(0,cnt+1,dow); return writeln(G.check()?ans+CO:-1),0; }