bzoj3571[Hnoi2014]画框

http://www.lydsy.com/JudgeOnline/problem.php?id=3571

好吧,裸的最小乘积匹配

现在才会KM算法。。。。。。。

#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;
  }
View Code

 

posted @ 2016-02-25 22:13  maijing  阅读(213)  评论(0编辑  收藏  举报