hdu2255:奔小康赚大钱
○| ̄|_○| ̄|_○| ̄|_。终于自己写出来了,虽然是模板题。首先是正确性的证明然后就是O(n^3)的优化,然而我就是这么弱智,弄了一个多小时才弄完;
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,n) for(int i=1;i<=n;i++) #define clr(x,c) memset(x,c,sizeof(x)) const int nmax=305; const int inf=(1<<30); int lx[nmax],ly[nmax],s[nmax],t[nmax],f[nmax],slack[nmax],n,v[nmax][nmax]; int read(){ int x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)){ x=x*10+c-‘0‘; c=getchar(); } return x; } int find(int x){ s[x]=1; rep(i,n) if(!t[i]){ int a=lx[x]+ly[i]-v[x][i]; if(!a){ t[i]=1; if(f[i]<0||find(f[i])){ f[i]=x; return 1; } } else slack[i]=min(slack[i],a); } return false; } int km(){ clr(lx,-0x3f);clr(ly,0);clr(f,-1); rep(i,n) rep(j,n) lx[i]=max(lx[i],v[i][j]); rep(i,n){ rep(j,n) slack[j]=inf; while(1){ clr(s,0);clr(t,0); if(find(i)) break; int a=inf; rep(j,n) if(!t[j]) a=min(slack[j],a); rep(j,n) if(s[j]) lx[j]-=a; rep(j,n) if(t[j]) ly[j]+=a; else slack[j]-=a; } } int ans=0; rep(i,n) if(f[i]) ans+=v[f[i]][i]; return ans; } int main(){ while(~scanf("%d",&n)){ rep(i,n) rep(j,n) v[i][j]=read(); printf("%d\n",km()); } return 0; }
时间: 2024-10-15 08:18:12