• bzoj3571


    题解:

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

    然后再加上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
    ",solve(le,ri));  
         }  
        return 0;  
    }  
  • 相关阅读:
    docker基础命令
    oracle 控制文件损坏处理
    mongodb 分片技术
    replcation set (复制集)配置过程 --mongodb
    redis API ---python
    MHA 高可用架构部署
    innoback 参数及使用说明
    Windows服务创建及发布
    DevOps 什么是 CI/CD?
    .NETReflectorVisualStudioExtension
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8319095.html
Copyright © 2020-2023  润新知