bzoj3571

同样的最小乘积XXX模型,这里显然是二分图带权匹配

我不会写KM……于是写了个费用流,由于是稠密图,会退化到n^4

然后本地跑了56s,交上去过了………………一定是我电脑太慢……

改天写个KM吧

  1 const inf=14000*14000;
  2 type node=record
  3        po,next,flow,cost:longint;
  4      end;
  5      point=record
  6        x,y:longint;
  7      end;
  8
  9 var e:array[0..2000010] of node;
 10     ma,pre,cur,p,d:array[0..145] of longint;
 11     v:array[0..145] of boolean;
 12     a,b,c:array[0..75,0..75] of longint;
 13     q:array[0..2000010] of longint;
 14     j,len,i,tt,t,n,ans:longint;
 15     p1,p2:point;
 16
 17 procedure add(x,y,f,c:longint);
 18   begin
 19     inc(len);
 20     e[len].po:=y;
 21     e[len].flow:=f;
 22     e[len].cost:=c;
 23     e[len].next:=p[x];
 24     p[x]:=len;
 25   end;
 26
 27 procedure build(x,y,f,c:longint);
 28   begin
 29     add(x,y,f,c);
 30     add(y,x,0,-c);
 31   end;
 32
 33 function spfa:boolean;
 34   var f,r,x,y,i,j:longint;
 35   begin
 36     fillchar(v,sizeof(v),false);
 37     for i:=1 to t do
 38       d[i]:=inf;
 39     d[0]:=0;
 40     f:=1;
 41     r:=1;
 42     q[1]:=0;
 43     while f<=r do
 44     begin
 45       x:=q[f];
 46       v[x]:=false;
 47       i:=p[x];
 48       while i<>-1 do
 49       begin
 50         y:=e[i].po;
 51         if e[i].flow>0 then
 52           if d[x]+e[i].cost<d[y] then
 53           begin
 54             d[y]:=d[x]+e[i].cost;
 55             cur[y]:=i;
 56             pre[y]:=x;
 57             if not v[y] then
 58             begin
 59               inc(r);
 60               q[r]:=y;
 61               v[y]:=true;
 62             end;
 63           end;
 64         i:=e[i].next;
 65       end;
 66       inc(f);
 67     end;
 68     if d[t]=inf then exit(false) else exit(true);
 69   end;
 70
 71 procedure change(j:longint);
 72   begin
 73     dec(e[j].flow);
 74     inc(e[j xor 1].flow);
 75   end;
 76
 77 function get:point;
 78   var i,j,x,y:longint;
 79   begin
 80     len:=-1;
 81     fillchar(p,sizeof(p),255);
 82     for i:=1 to n do
 83     begin
 84       build(0,i,1,0);
 85       build(i+n,t,1,0);
 86     end;
 87     x:=1; y:=1;
 88     for i:=1 to n do
 89       for j:=1 to n do
 90       begin
 91         build(i,j+n,1,c[i,j]);
 92         if c[i,j]<c[x,y] then
 93         begin
 94           x:=i;
 95           y:=j;
 96         end;
 97       end;
 98     ma[y+n]:=x;
 99     i:=p[x];
100     while i<>-1 do
101     begin
102       if (e[i].po=y+n) then change(i);
103       if e[i].po=0 then change(i xor 1);
104       i:=e[i].next;
105     end;
106     i:=p[y+n];
107     while i<>-1 do
108     begin
109       if e[i].po=t then
110       begin
111         change(i);
112         break;
113       end;
114       i:=e[i].next;
115     end;
116     while spfa do
117     begin
118       i:=t;
119       while i<>0 do
120       begin
121         j:=cur[i];
122         change(j);
123         if (i>n) and (i<>t) then
124           ma[i]:=pre[i];
125         i:=pre[i];
126       end;
127     end;
128     get.x:=0; get.y:=0;
129     for i:=1 to n do
130     begin
131       j:=ma[i+n];
132      // write(j,‘ ‘);
133       inc(get.x,a[j,i]);
134       inc(get.y,b[j,i]);
135     end;
136    // writeln;
137     if get.x*get.y<ans then ans:=get.x*get.y;
138   end;
139
140 function cross(a,b,c:point):longint;
141   begin
142     exit((a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x));
143   end;
144
145 procedure work(p1,p2:point);
146   var p:point;
147       i,j:longint;
148   begin
149     for i:=1 to n do
150       for j:=1 to n do
151         c[i,j]:=a[i,j]*(p1.y-p2.y)+b[i,j]*(p2.x-p1.x);
152     p:=get;
153     if cross(p2,p,p1)>=0 then exit;
154     work(p1,p);
155     work(p,p2);
156   end;
157
158 begin
159   readln(tt);
160   while tt>0 do
161   begin
162     dec(tt);
163     readln(n);
164     t:=2*n+1;
165     for i:=1 to n do
166       for j:=1 to n do
167         read(a[i,j]);
168     for i:=1 to n do
169       for j:=1 to n do
170         read(b[i,j]);
171     for i:=1 to n do
172       for j:=1 to n do
173         c[i,j]:=a[i,j];
174     ans:=14000*140000;
175     p1:=get;
176     for i:=1 to n do
177       for j:=1 to n do
178         c[i,j]:=b[i,j];
179     p2:=get;
180     work(p1,p2);
181     writeln(ans);
182   end;
183 end.

时间: 2024-10-05 16:22:26

bzoj3571的相关文章

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> #incl

bzoj3571: [Hnoi2014]画框 最小乘积匹配+最小乘积XX总结,

思路大概同bzoj2395(传送门:http://www.cnblogs.com/DUXT/p/5739864.html),还是将每一种匹配方案的Σai看成x,Σbi看成y,然后将每种方案转化为平面上的点,再用km去找最远的点就行了. 然而几个月前就学过km且到现在还未写过一道km的题的我并不知道km如何对于负权给出最优解.... #define XX 某传统算法(例如:最小生成树,二分图最优带权匹配什么的) 顺便总结一下最小乘积XX 即对于XX引入两个权值的概念(或是多个权值,一般是两个),看

【挖坑】thusc前一周计划2016.5.30-2016.6.3

首先开了徐姥爷blog&&AC记录里的几题,然后还有几个算法&&模板题要搞掉. 今天&&明天: bzoj3571/3083/2752/2727/2728/1062/1063/1065/1797/4621 这10题里至少完成其中7题吧. 算法list: dominator tree(模板题还没找) 动态树分治(模板题4012,1095) 仙人掌缩点+DP(题1023,4316) 这3个至少完成2个吧. bzoj AC数: 下限690吧,不过不能刷一点意义都没有