题目链接

戳我

\(Solution\)

这一题很像最小乘积生成树.只是把\(kruskal\)变为了\(km\)/费用流

现在来讲一讲最小乘积生成树.首先将\(\sum a_i\)和\(\sum b_i\)看为坐标轴上的点\((x,y)\)

\(step 1:\) 首先找出离\(x\)最近的点和离\(y\)最近的点

\(step 2:\) 找出距离\(A,B\)最远的\(C\)(\(C\)要在\(A,B\)左边)

\(step 3:\) 递归处理\(AC\)和\(CB\),直到找不到\(C\)为止

现在来讲一下怎么求\(C\),我们可以通过向量的叉积来算.

因为\(C\)要离\(AB\)最远等价于\(S_{\Delta ABC}\)最大即:\(\overrightarrow{A C}*\overrightarrow{A B}\)最小

\[\overrightarrow{A C}*\overrightarrow{A B}
\]

\[=(X_B-X_A)*(Y_C-Y_A)-(Y_B-Y_A)*(X_C-X_A)
\]

\[=(X_B-X_A)*Y_C+(Y_A-Y_B)*X_C+ans
\]

ans为一个常数,不用管他.

然后我们直接将权值/费用改为\((X_B-X_A)*b+(Y_A-Y_B)*a\)在跑一遍\(km/\)费用流即可

\(luogu\)没过T了,\(bzoj\)过了

\(Code\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int read() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
struct node {
int x,y;
bool operator == (const node &z)const {
return x==z.x&&y==z.y;
}
};
node operator - (const node & a , const node & b) {
return (node) {
a.x-b.x,a.y-b.y
};
}
int calc(node x, node y) {
return (x.x * y.y) - (x.y * y.x);
}
node minx;
struct node1 {
int to,next,v,w;
} a[1000001];
int dis[100001],f[100001],pre[100001],fa[100001],s,t,n,m,head[100001],cnt,x,y,z,c,A[100][100],B[100][100];
void add(int x,int y,int c,int v) {
a[++cnt].to=y,a[cnt].next=head[x],a[cnt].v=c,a[cnt].w=v,head[x]=cnt;
a[++cnt].to=x,a[cnt].next=head[y],a[cnt].v=0,a[cnt].w=-v,head[y]=cnt;
}
queue < int > q;
int spfa() {
q.push(s);
for(int i=s; i<=t; i++)
dis[i]=2147483647,f[i]=0;
f[s]=1,dis[s]=0;
int inf=dis[s+1];
while(!q.empty()) {
int now=q.front();
q.pop(),f[now]=0;
for(int i=head[now]; i; i=a[i].next) {
int v=a[i].to;
if(dis[v]>dis[now]+a[i].w&&a[i].v) {
dis[v]=dis[now]+a[i].w,pre[v]=i,fa[v]=now;
if(!f[v])
f[v]=1,q.push(v);
}
}
}
if(dis[t]!=inf)
return 1;
return 0;
}
int ans1,ans,minn=2147483647;
void answer() {
while(spfa()) {
int minx=2147483647;
for(int i=t; i!=s; i=fa[i])
minx=min(minx,a[pre[i]].v);
ans+=minx,ans1+=dis[t]*minx;
for(int i=t; i!=s; i=fa[i])
a[pre[i]].v-=minx,(pre[i]%2)?a[pre[i]+1].v+=minx:a[pre[i]-1].v+=minx;
}
}
node work(int fx,int fy) {
cnt=0,s=0,t=2*n+1;
for(int i=s; i<=t; i++)
head[i]=0;
for(int i=1; i<=n; i++) {
add(s,i,1,0),add(i+n,t,1,0);
for(int j=1; j<=n; j++)
add(i,j+n,1,A[i][j]*fx+B[i][j]*fy);
}
answer();
int x=0,y=0;
for(int i=1; i<=n; i++)
for(int j=head[i]; j; j=a[j].next)
if(!a[j].v&&a[j].to)
x+=A[i][a[j].to-n],y+=B[i][a[j].to-n];
node ans2;
ans2.x=x,ans2.y=y;
if(x*y<minn)
minn=x*y;
return ans2;
}
void devide(node l,node r) {
node mid=work(l.y-r.y,r.x-l.x);
if(l==mid||mid==r) return ;
devide(l,mid),devide(mid,r);
}
main() {
int T=read();
node l,r;
while(T--) {
n=read(),minn=2147483647;
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();
l=work(1,0),r=work(0,1);
devide(l,r);
printf("%d\n",minn);
}
}

「HNOI 2014」 画框的更多相关文章

  1. 「HNOI 2014」 江南乐

    \(Description\) \(n\)堆石子,每堆石子有\(s_i\)个,两个人轮流操作,每次可以将一对不少于\(F\)的石子尽量平均分成\(m\)堆,\(m\)每次自选,不能操作者输.共有\(T ...

  2. 「HNOI 2014」米特运输

    题目链接 戳我 \(Describe\) 谁出的题目啊?这么长的题面,看完就滚粗了.强烈谴责 给一棵树,每个点有一个权值,要求修改一些权值,使: 一个点的权值必须是其所有儿子的权值之和 一个点的儿子权 ...

  3. LOJ#3054. 「HNOI 2019」鱼

    LOJ#3054. 「HNOI 2019」鱼 https://loj.ac/problem/3054 题意 平面上有n个点,问能组成几个六个点的鱼.(n<=1000) 分析 鱼题,劲啊. 容易想 ...

  4. 「HNOI 2019」白兔之舞

    一道清真的数论题 LOJ #3058 Luogu P5293 题解 考虑$ n=1$的时候怎么做 设$ s$为转移的方案数 设答案多项式为$\sum\limits_{i=0}^L (sx)^i\bin ...

  5. 「HNOI 2016」 序列

    \(Description\) 给你一个序列,每次询问一个区间,求其所有子区间的最小值之和 \(Solution\) 这里要用莫队算法 首先令\(val\)数组为原序列 我们考虑怎么由一个区间\([l ...

  6. 「HNOI 2015」实验比较

    \(Description\) 有\(n\)个元素,对于每个元素\(x_i\)最多知道一个形如\(x_j < x_i\)或\(x_j=x_i\)的条件,问有多少合法的序列.合法的序列满足每个元素 ...

  7. 「HNOI 2015」亚瑟王

    \(Description\) 有\(n\)张卡牌,每一张卡牌有\(p_i\)的概率发动,并造成\(d_i\)点伤害.一共有\(r\)轮,每一轮按照编号从小到大依次考虑,如果这张牌已经发动过则跳过该牌 ...

  8. 「HNOI 2015」菜肴制作

    题目链接 戳我 \(Description\) 有若干限制,需要求一个\(1\)到\(n\)的排列,每个限制\((x,y)\)表示\(x\)必须在\(j\)之前,并要求所求的排列满足所有限制并让\(1 ...

  9. 「HNOI 2015」落忆枫音

    题目链接 戳我 \(Description\) 给一张\(n\)割点\(m\)条边的\(DAG\),保证点\(1\)不存在入边,现在需要在\(DAG\)中加入一条不在原图中的边\((x,y)\),求这 ...

随机推荐

  1. 2.Hadoop集群搭建之Hadoop(包含HDFS和Yarn)安装

    前期准备 下载JDK 6.0以上版本 下载Hadoop 2.4.1 1. 安装JDK 因为Hadoop是Java开发的,所以需要安装JDK,建议JDK 6.0以上. 解压JDK tar -zxvf J ...

  2. Spring DI的配置使用

    1.1.1 依赖和依赖注入Spring IOC容器的依赖有两层含义:Bean依赖容器和容器注入Bean的依赖资源:a.Bean依赖容器:也就是说Bean要依赖于容器,这里的依赖是指容器负责创建Bean ...

  3. re模块之re.match

    re模块--python 正则表达式 正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配. Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达 ...

  4. 32. Longest Valid Parentheses (Stack; DP)

    Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...

  5. ssh的发展历程与基本原理

    一.ssh是什么 SSH(Secure Shell)是一个提供数据通信安全.远程登录.远程指令执行等功能的安全网络协议,最初提出目的是替代非安全的Telnet.rsh.rexec等远程Shell协议. ...

  6. 一张图5分钟熟悉MarkDown的基本语法

    看到zealer上面有介绍MarkDown的,以前在老罗的发布会也听说过,说锤子便签支持MarkDown,但是不知道有什么用,现在来看看,确实不错. MarkDown的好处是让你可以专注于写字本身,而 ...

  7. Openssl pkcs7命令

    一.简介 pkcs7命令用于处理DER或者PEM格式的pkcs#7文件.   二.语法 openssl pkcs7 [-inform PEM|DER] [-outform PEM|DER] [-in ...

  8. Java设计模式(2)——工厂方法模式

    工厂方法模式同样属于类的创建型模式又被称为多态工厂模式.工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中.核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色, ...

  9. bash 环境配置及脚本

    bash是 Bourne Again Shell简称 ,从unix系统的sh发展而来 查看当前shellecho $SHELL查看系统支持的shellcat /etc/shells cd /binls ...

  10. 安装DotNetCore.1.0.0-VS2015Tools.Preview2一直失败

    266C:22B0][2016-08-01T23:02:29]i052: Condition 'WixBundleInstalled OR NOT(NetFx45Release < 378675 ...