bzoj 3571: [Hnoi2014]画框 最优乘积匹配
2016-05-16 19:17
288 查看
显然可以把一种匹配看成点(x,y),x为第一种边权的和,y为第二种边权的和。那么这个匹配的值为x*y,题中要寻找最小的x*y。
令k=x*y,那么对于匹配(x,y),在直线y=k/x上方的匹配都是没有它更优的;求最优乘积匹配的方法同最小乘积生成树。首先找到x最小的匹配(x1,y1)和y最小的匹配(x2,y2)作为初始的边界。令(x1,y1)为左边界,(x2,y2)为右边界的解为solve(x1,y1,x2,y2)。我们找到离直线(x1,y1)->(x2,y2)最远的且在直线下方的(x3,y3),用x3*y3更新答案,然后递归(x1,y1,x3,y3)和(x3,y3,x2,y2)即可。
AC代码如下:
by lych
2016.5.16
令k=x*y,那么对于匹配(x,y),在直线y=k/x上方的匹配都是没有它更优的;求最优乘积匹配的方法同最小乘积生成树。首先找到x最小的匹配(x1,y1)和y最小的匹配(x2,y2)作为初始的边界。令(x1,y1)为左边界,(x2,y2)为右边界的解为solve(x1,y1,x2,y2)。我们找到离直线(x1,y1)->(x2,y2)最远的且在直线下方的(x3,y3),用x3*y3更新答案,然后递归(x1,y1,x3,y3)和(x3,y3,x2,y2)即可。
AC代码如下:
#include<iostream> #include<cstdio> #include<cstring> #define N 155 #define M 40005 #define inf 1000000000 using namespace std; int n,gol,ans,a ,b ,d ,pre ,h[M+5]; bool ok ,bo ; struct point{ int x,y; }; bool spfa(int u,int v){ memset(bo,1,sizeof(bo)); memset(d,0x3f,sizeof(d)); d[0]=0; int head=0,tail=1; h[1]=0; while (head!=tail){ head=head%M+1; int x=h[head],y,z; bo[x]=1; for (y=1; y<=gol; y++) if (ok[x][y] && (z=d[x]+a[x][y]*u+b[x][y]*v)<d[y]){ d[y]=z; pre[y]=x; if (bo[y]){ bo[y]=0; tail=tail%M+1; h[tail]=y; } } } return d[gol]<inf; } point calc(int u,int v){ int i,j,x=0,y=0; for (i=1; i<=n; i++) for (j=1; j<=n; j++){ ok[i][j+n]=1; ok[j+n][i]=0; } for (i=1; i<=n; i++){ ok[0][i]=ok[i+n][gol]=1; ok[i][0]=ok[gol][i+n]=0; } while (spfa(u,v)) for (i=gol; i; i=pre[i]){ ok[pre[i]][i]=0; ok[i][pre[i]]=1; x+=a[pre[i]][i]; y+=b[pre[i]][i]; } ans=min(ans,x*y); return (point){x,y}; } void solve(point u,point v){ point p=calc(u.y-v.y,v.x-u.x); if ((v.x-p.x)*(u.y-p.y)-(u.x-p.x)*(v.y-p.y)){ solve(u,p); solve(p,v); } } int main(){ int cas; scanf("%d",&cas); while (cas--){ scanf("%d",&n); ans=inf; int i,j; for (i=1; i<=n; i++) for (j=1; j<=n; j++){ scanf("%d",&a[i][j+n]); a[j+n][i]=-a[i][j+n]; } for (i=1; i<=n; i++) for (j=1; j<=n; j++){ scanf("%d",&b[i][j+n]); b[j+n][i]=-b[i][j+n]; } gol=n<<1|1; point u=calc(1,0),v=calc(0,1); solve(u,v); printf("%d\n",ans); } return 0; }
by lych
2016.5.16
相关文章推荐
- MSSQL之六 数据库设计
- Linux 安装svn
- 计算机网络(原书第六版) 第二章笔记
- 【网络】TCP协议
- 备忘录
- Python With
- 写文献综述的二十八个要点
- 数据库的设计范式
- Linux下切换python版本
- swt 高级控件介绍(1)
- Git使用http clone客户端保存用户名密码
- 冒泡排序
- 栈的顺序存储——共享栈
- Oracle 11g改密码有效期
- leetcode.179. Largest Number
- JSON net.sf.jason使用
- .NET J2EE APP全局会话架构运用场景
- JS验证码
- [BZOJ4521][Cqoi2016]手机号码
- OpenJudge C16D Extracurricular Sports(构造/大数)