Description
小T准备在家里摆放几幅画,为此他买来了N幅画和N个画框。为了体现他的品味,小T希望能合理地搭配画与画框,使得其显得既不过于平庸也不太违和。对于第
幅画与第 个画框的配对,小T都给出了这个配对的平凡度Aij 与违和度Bij
。整个搭配方案的总体不和谐度为每对画与画框平凡度之和与每对画与画框违和度的乘积。具体来说,设搭配方案中第i幅画与第Pi个画框配对,则总体不和谐度为
小T希望知道通过搭配能得到的最小的总体不和谐度是多少。
Input
输入文件第 行是一个正整数T ,表示数据组数,接下来是T组数据。 对于每组数据,第 行是一个正整数N,表示有N对画和画框。
第2到第N+1行,每行有N个非负整数,第i+1 行第j个数表示Aij 。 第N+2到第2*N+1行,每行有N个非负整数,第i+N+1
行第j个数表示Bij 。
Output
包含T行,每行一个整数,表示最小的总体不和谐度
Sample Input
1
3
4 3 2
2 3 4
3 2 1
2 3 2
2 2 4
1 1 3
Sample Output
30
HINT
第1幅画搭配第3个画框,第2幅画搭配第1个画框,第3 幅画搭配第2个画框,则总体不和谐度为30
N<=70,T<=3,Aij<=200,Bij<=200
题解
搞了半天突然就发现就是个最小乘积匹配嘛…
x坐标看成A的和
y坐标看成B的和
类似最小乘积生成树那样做一做
把kurskal换成带权匹配就可以了…
文化课真是伤脑子
spfa又写错 柿子又推错药丸了啊
不会KM写了个费用流水过去
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int stack[20];
inline void write(int x)
{
if(x<0){putchar('-');x=-x;}
if(!x){putchar('0');return;}
int top=0;
while(x)stack[++top]=x%10,x/=10;
while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(int x){write(x);putchar('\n');}
struct node{int x,y,c,d,next;}a[210000];int len,last[210];
void ins(int x,int y,int c,int d)
{
len++;a[len].x=x;a[len].y=y;a[len].c=c;a[len].d=d;
a[len].next=last[x];last[x]=len;
len++;a[len].x=y;a[len].y=x;a[len].c=0;a[len].d=-d;
a[len].next=last[y];last[y]=len;
}
queue<int> li;
bool v[210];
int d[210],st,ed,pre[210],tmp[210];
bool spfa()
{
memset(v,false,sizeof(v));v[st]=true;
memset(d,63,sizeof(d));d[st]=0;
li.push(st);
while(!li.empty())
{
int x=li.front();li.pop();v[x]=false;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(d[y]>d[x]+a[k].d&&a[k].c)
{
d[y]=d[x]+a[k].d;
pre[y]=x;tmp[y]=k;
if(!v[y])v[y]=true,li.push(y);
}
}
}
return d[ed]<1e9;
}
int mcf()
{
int minn,ret=0;
while(spfa())
{
int x=ed;minn=999999999;
while(x!=st)
{
minn=min(minn,a[tmp[x]].c);
x=pre[x];
}
ret+=minn*d[ed];x=ed;
while(x!=st)
{
a[tmp[x]].c-=minn;a[tmp[x]^1].c+=minn;
x=pre[x];
}
}
return ret;
}
struct pt
{
int x,y;
pt(){}
pt(int _x,int _y){x=_x;y=_y;}
};
int A[80][80],B[80][80],n;
void init(int x1,int y1,int x2,int y2)
{
st=2*n+1;ed=2*n+2;
len=1;memset(last,0,sizeof(last));
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
ins(i,j+n,1,A[i][j]*(y1-y2)+B[i][j]*(x2-x1));
for(int i=1;i<=n;i++)ins(st,i,1,0),ins(i+n,ed,1,0);
}
int multi(pt p0,pt p1,pt p2)
{
int u1,u2,v1,v2;
u1=p1.x-p0.x;u2=p2.x-p0.x;
v1=p1.y-p0.y;v2=p2.y-p0.y;
return (LL)u1*v2-(LL)u2*v1;
}
int ans,now;
void query(pt u1,pt u2)
{
init(u1.x,u1.y,u2.x,u2.y);
int S=mcf();
int s1=0,s2=0,cnt=0;
for(int i=1;i<=len;i++)if(a[i].x>=1&&a[i].x<=n&&a[i].y>=n+1&&a[i].y<=2*n&&!a[i].c)
{
int u=a[i].x,v=a[i].y-n;
s1+=A[u][v];s2+=B[u][v];
cnt++;
}
pt u3=pt(s1,s2);
if(multi(u3,u1,u2)>=0)return ;
ans=min(ans,s1*s2);
query(u1,u3);
query(u3,u2);
}
int main()
{
// freopen("7.in","r",stdin);
int T=read();while(T--)
{
len=1;memset(last,0,sizeof(last));
n=read();st=2*n+1;ed=2*n+2;
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)A[i][j]=read();
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)B[i][j]=read();
ans=(1<<31-1);
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
ins(i,j+n,1,A[i][j]);
for(int i=1;i<=n;i++)ins(st,i,1,0),ins(i+n,ed,1,0);
int qqq=mcf();
int nn1=0,nn2=0;
for(int i=1;i<=len;i++)if(a[i].x>=1&&a[i].x<=n&&a[i].y>=n+1&&a[i].y<=2*n&&!a[i].c)
{
int u=a[i].x,v=a[i].y-n;
nn1+=A[u][v];nn2+=B[u][v];
}
len=1;memset(last,0,sizeof(last));
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
ins(i,j+n,1,B[i][j]);
for(int i=1;i<=n;i++)ins(st,i,1,0),ins(i+n,ed,1,0);
qqq=mcf();
int nn3=0,nn4=0;
for(int i=1;i<=len;i++)if(a[i].x>=1&&a[i].x<=n&&a[i].y>=n+1&&a[i].y<=2*n&&!a[i].c)
{
int u=a[i].x,v=a[i].y-n;
nn3+=A[u][v];nn4+=B[u][v];
}
ans=min(nn1*nn2,nn3*nn4);
query(pt(nn1,nn2),pt(nn3,nn4));
pr2(ans);
}
return 0;
}