The idea is probably the same as bzoj2395 (Portal: http://www.cnblogs.com/DUXT/p/5739864.html), or σai of each matching scheme as x,σbi as Y, and then converting each scheme to a point on a plane, Then use the KM to find the farthest point on the line.
A few months ago, however, I did not know how to get the best solution for the negative right ....
#define XX a traditional algorithm (for example: the minimum spanning tree, the binary graph of the optimal band Right match what)
By the way, summarize the minimum product XX
That is, XX introduced the concept of two weights (or a plurality of weights, generally two), seemingly impossible, but can each set of feasible solutions of two sum into a plane within a point, and then you can find a very beautiful nature that the optimal solution must be on the convex hull, so you can use a similar to the fast packet algorithm , is still using XX to find a certain in the convex hull two points, and then again using XX for division, recursive underground to find, clear boundary conditions (generally a fork can be easily done), so that the problem is easily solved. (It seems that a template like this, basic all similar problems can be resolved)
1#include <iostream>2#include <cstdio>3#include <cstring>4#include <algorithm>5#include <cmath>6 using namespacestd;7 #defineMAXN 1008 #defineINF 1000000009 Ten intCases,n; One intA[MAXN][MAXN],B[MAXN][MAXN],VAL[MAXN][MAXN],SLACK[MAXN],VALX[MAXN],VALY[MAXN],LINKY[MAXN]; A BOOLVISX[MAXN],VISY[MAXN]; - - structpoint{ the intx, y; - }ans; - -Pointoperator-(point A,point b) {return(point) {a.x-b.x,a.y-b.y};} + Double operator* (Point A,point b) {returna.x*b.y-a.y*b.x;} - + BOOLFindintx) { Avisx[x]=1; at for(inty=1; y<=n;y++) - if(!Visy[y]) { - intt=valx[x]+valy[y]-Val[x][y]; - if(!t) { -visy[y]=1; - if(!linky[y]| |find (Linky[y])) { inlinky[y]=x; - return 1; to } + } - Elseslack[y]=min (slack[y],t); the } * return 0; $ }Panax Notoginseng - Point km () { thememset (Valx,0,sizeof(VALX)); +memset (Valy,0,sizeof(Valy)); Amemset (Linky,0,sizeof(Linky)); the for(intI=1; i<=n;i++) + for(intj=1; j<=n;j++) -valx[i]=Max (valx[i],val[i][j]); $ for(intx=1; x<=n;x++){ $memset (Slack, the,sizeof(slack)); - while(1){ -memset (VISX,0,sizeof(VISX)); thememset (Visy,0,sizeof(Visy)); - if(Find (x)) Break;Wuyi intD=inf; the for(intI=1; i<=n;i++)if(!visy[i]) d=min (d,slack[i]); - for(intI=1; i<=n;i++)if(Visx[i]) valx[i]-=D; Wu for(intI=1; i<=n;i++)if(Visy[i]) valy[i]+=D; - } About } $Point now={0,0}; - for(intI=1; i<=n;i++) now.x+=a[linky[i]][i],now.y+=B[linky[i]][i]; - if((Ans.x==inf&&ans.y==inf) | | (ANS.X*ANS.Y>NOW.X*NOW.Y)) ans=Now ; - returnNow ; A } + the BOOL operator= = (Point A,point b) {returna.x==b.x&&a.y==B.y;} - $ voidSolve (point X,point y) { the for(intI=1; i<=n;i++) the for(intj=1; j<=n;j++) theval[i][j]=b[i][j]* (x.x-y.x) +a[i][j]* (y.y-x.y); thePoint z=km (); - if((z-x) * (y-z) <=0)return; in solve (x,z); the solve (z,y); the } About the intMain () { thescanf"%d",&cases); the while(cases--){ +scanf"%d",&n); -ans.x=ans.y=inf; the for(intI=1; i<=n;i++)Bayi for(intj=1; j<=n;j++) scanf ("%d",&a[i][j]); the for(intI=1; i<=n;i++) the for(intj=1; j<=n;j++) scanf ("%d",&b[i][j]); - Point minx,miny; - for(intI=1; i<=n;i++) the for(intj=1; j<=n;j++) val[i][j]=-A[i][j]; theminx=km (); the for(intI=1; i<=n;i++) the for(intj=1; j<=n;j++) val[i][j]=-B[i][j]; -miny=km (); the solve (minx,miny); theprintf"%d\n", ans.x*ans.y); the }94 return 0; the}
View Code
bzoj3571: [Hnoi2014] frame minimum product match + minimum product XX summary,