bzoj3571[Hnoi2014]画框
http://www.lydsy.com/JudgeOnline/problem.php?id=3571
好吧,裸的最小乘积匹配
现在才会KM算法。。。。。。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<map> #include<utility> #include<set> #include<bitset> #include<vector> #include<functional> #include<deque> #include<cctype> #include<climits> #include<complex> #include<cassert> //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL; typedef double DB; typedef pair<int,int> PII; typedef pair<DB,DB> PDD; typedef complex<DB> CP; typedef vector<int> VI; #define mmst(a,v) memset(a,v,sizeof(a)) #define mmcy(a,b) memcpy(a,b,sizeof(a)) #define fill(a,l,r,v) fill(a+l,a+r+1,v) #define re(i,a,b) for(i=(a);i<=(b);i++) #define red(i,a,b) for(i=(a);i>=(b);i--) #define fi first #define se second #define mp(a,b) make_pair(a,b) #define pb(a) push_back(a) #define SF scanf #define PF printf #define two(k) (1<<(k)) #define SZ(x) (int(x.size())) #define all(x) (x).begin(),(x).end() #define ire(i,v,x) for(i=0,v=i<SZ(x)?x[i]:0;i<SZ(x);v=x[++i]) template<class T>inline T sqr(T x){return x*x;} template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;} template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} inline int sgn(DB x){if(abs(x)<1e-9)return 0;return(x>0)?1:-1;} const DB Pi=acos(-1.0); int gint() { int res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } LL gll() { LL res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } const int maxn=75; const int inf=0x3f3f3f3f; int n; int A[maxn][maxn],B[maxn][maxn]; int ans; int val[maxn][maxn]; int lx[maxn],ly[maxn],p[maxn],from[maxn],slk[maxn]; int ci,visx[maxn],visy[maxn]; int dfs(int i) { int j; visx[i]=ci; re(j,1,n) if(lx[i]+ly[j]>val[i][j]) upmin(slk[j],lx[i]+ly[j]-val[i][j]); else if(visy[j]!=ci) { visy[j]=ci; if(!from[j] || dfs(from[j])){from[j]=i;return 1;} } return 0; } void KM() { int i,j,cost; re(i,1,n)re(j,1,n)val[i][j]=-val[i][j]; re(i,1,n) { lx[i]=-inf;ly[i]=0;from[i]=0; re(j,1,n)upmax(lx[i],val[i][j]); } re(i,1,n) { re(j,1,n)slk[j]=inf; ci++; while(!dfs(i)) { int d=inf; re(j,1,n)if(visy[j]!=ci)upmin(d,slk[j]); re(j,1,n)if(visx[j]==ci)lx[j]-=d; re(j,1,n)if(visy[j]==ci)ly[j]+=d; re(j,1,n)slk[j]=inf; ci++; } } re(i,1,n)p[from[i]]=i; re(i,1,n)re(j,1,n)val[i][j]=-val[i][j]; } void solve(int x1,int y1,int x2,int y2) { int i,j,res=x1*y2-x2*y1,x=0,y=0; re(i,1,n)re(j,1,n)val[i][j]=(y1-y2)*A[i][j]+(x2-x1)*B[i][j]; KM(); re(i,1,n)res+=val[i][p[i]],x+=A[i][p[i]],y+=B[i][p[i]]; if(res>=0)return; upmin(ans,x*y); solve(x1,y1,x,y); solve(x,y,x2,y2); } int main() { freopen("frame.in","r",stdin); freopen("frame.out","w",stdout); int i,j,T=gint(); while(T--) { n=gint(); re(i,1,n)re(j,1,n)A[i][j]=gint(); re(i,1,n)re(j,1,n)B[i][j]=gint(); int x1=0,y1=0,x2=0,y2=0; mmcy(val,A); KM(); re(i,1,n)x1+=A[i][p[i]],y1+=B[i][p[i]]; mmcy(val,B); KM(); re(i,1,n)x2+=A[i][p[i]],y2+=B[i][p[i]]; ans=min(x1*y1,x2*y2); solve(x1,y1,x2,y2); cout<<ans<<endl; } return 0; }