1. 程式人生 > >[bzoj3571][網路流-費用流][最小乘積匹配]畫框

[bzoj3571][網路流-費用流][最小乘積匹配]畫框

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; }