题解:

似乎是什么乘积最小生成树

然后再加上km

代码:

#include<bits/stdc++.h> 
const int N=75;  
using namespace std;  
struct poi{int x,y;}le,ri;  
int cas,n,A[N][N],B[N][N],g[N][N],lx[N],ly[N],mat[N],sla[N],vx[N],vy[N];  
int operator ==(poi a,poi b){return a.x==b.x&&a.y==b.y;}  
int dfs(int x)
{  
    vx[x]=1;  
    for (int y=1;y<=n;y++)  
     if (!vy[y])
      {  
        int t=lx[x]+ly[y]-g[x][y];  
        if (!t)
         {  
            vy[y]=1;  
            if (!mat[y]||dfs(mat[y])){mat[y]=x;return 1;}  
         }  
        else sla[y]=min(sla[y],t);  
      }  
    return 0;  
}  
poi KM()
{  
    memset(lx,0,sizeof(lx));
    memset(ly,0,sizeof(ly));
    memset(mat,0,sizeof(mat));  
    for (int i=1;i<=n;i++)
     for (int j=1;j<=n;j++) lx[i]=max(lx[i],g[i][j]);  
    for (int x=1;x<=n;x++)
     {  
        memset(sla,63,sizeof(sla));  
        while (1)
         {  
            memset(vx,0,sizeof(vx));
            memset(vy,0,sizeof(vy));  
            if (dfs(x)) break;  
            int d=1e9;  
            for (int i=1;i<=n;i++)
             if (!vy[i]) d=min(d,sla[i]);  
            for (int i=1;i<=n;i++)
             {  
                if (vx[i]) lx[i]-=d;  
                if (vy[i]) ly[i]+=d;  
             }  
         }  
     }  
    poi ans=(poi){0,0};  
    for (int i=1;i<=n;i++) ans.x+=A[mat[i]][i],ans.y+=B[mat[i]][i];  
    return ans;  
}  
int solve(poi l,poi r)
{  
    for (int i=1;i<=n;i++)
     for (int j=1;j<=n;j++) g[i][j]=A[i][j]*(r.y-l.y)+B[i][j]*(l.x-r.x);  
    poi mid=KM();  
    if (l==mid||r==mid) return min(l.x*l.y,r.x*r.y);  
    return min(solve(l,mid),solve(mid,r));  
}  
int main()
{  
    scanf("%d",&cas);  
    while (cas--)
     {  
        scanf("%d",&n);  
        for (int i=1;i<=n;i++)
         for (int j=1;j<=n;j++) scanf("%d",&A[i][j]);  
        for (int i=1;i<=n;i++)
         for (int j=1;j<=n;j++) scanf("%d",&B[i][j]);  
        for (int i=1;i<=n;i++)
         for (int j=1;j<=n;j++) g[i][j]=-A[i][j];le=KM();  
        for (int i=1;i<=n;i++)
         for (int j=1;j<=n;j++) g[i][j]=-B[i][j];ri=KM();  
        printf("%d\n",solve(le,ri));  
     }  
    return 0;  
}  

 

posted on 2018-01-19 22:30  宣毅鸣  阅读(115)  评论(0编辑  收藏  举报