Solution -「洛谷 P6158」封锁
\(\mathcal{Description}\)
Link.
给定一个 \(n\times n\) 的格点图,横纵相邻的两格点有一条边权为二元组 \((w,e)\) 的边。求对于 \(S=(1,1)\) 和 \(T=(n,n)\) 的一个割,使得 \((\sum w)(\sum c)\) 最小。
\(n\le400\)。
\(\mathcal{Solution}\)
套路题,P5540 + P4001。所以我把这两题题解合二为一。
假设边权都是普通的数字,考虑怎么快速求出这个格点图的最小割。可以发现,这个图一定是一个平面图,那么把它形象化为图形,脑补一下得出一个割肯定是一条完整的曲线,从图的左下方贯穿到图的右上方。所以建立左下方和右上方的超级源汇,每条边相当于连接其左右两个面,最后求源汇之间的最短路即为原图最小割。
回到本题,对于任意一个割,设其 \(\sum w=w_0\),\(\sum e=e_0\),将它体现为一个坐标 \((w_0,e_0)\),问题就转化为:\(\mathbb R^2\) 的一象限有若干个点,求出其中 \(xy\) 最小的点。
记 \(A(x_1,y_1)\) 为这些点中 \(x\) 最小的,\(B(x_2,y_2)\) 为 \(y\) 最小的(都能直接求出),考虑在 \(AB\) 的下方取出一个特殊的点 \(C(x_3,y_3)\),最大化 \(S_{\triangle ABC}\)。推一下式子:
S_{\triangle ABC}&=\frac{-\vec{AB}\times \vec{AC}}{2}\\
&=-\frac{1}{2}[(x_2-x_1)(y_3-y_1)-(x_3-x_1)(y_2-y_1)]\\
&=-\frac{1}2[(y_1-y_2)x_3+(x_2-x_1)y_3-x_2y_1+x_1y_2]
\end{aligned}
\]
把 \((y_1-y_2)w+(x_2-x_1)e\) 作为边 \((w,e)\) 的权,跑最小割即得 \(C\)。用 \(C\) 更新答案最后,分治处理 \((A,C)\) 和 \((C,B)\) 直到 \(C\) 不存在终止,答案就求到啦。
\(\mathcal{Code}\)
/* Clearink */
#include <queue>
#include <cstdio>
#include <assert.h>
typedef long long LL;
inline int rint () {
int x = 0, f = 1; char s = getchar ();
for ( ; s < '0' || '9' < s; s = getchar () ) f = s == '-' ? -f : f;
for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' );
return x * f;
}
inline void chkmin ( LL& a, const LL b ) { b < a && ( a = b, 0 ); }
const int MAXN = 400, INF = 0x3f3f3f3f;
int n, S, T;
LL coeW, coeE, ans = 1ll << 60;
struct Value {
LL w, e;
Value ( const LL v = 0 ): w ( v ), e ( v ) {}
Value ( const LL a, const LL b ): w ( a ), e ( b ) {}
inline operator LL () const { return w + e; }
inline LL operator * ( const Value& v ) const { return w * v.e - e * v.w; }
inline Value operator + ( const Value& v ) const { return { w + v.w, e + v.e }; }
inline Value operator - ( const Value& v ) const { return { w - v.w, e - v.e }; }
inline bool operator < ( const Value& v ) const {
return coeW * w + coeE * e < coeW * v.w + coeE * v.e;
}
};
typedef std::pair<Value, int> PVI;
struct Graph {
static const int MAXND = MAXN * MAXN + 2, MAXEG = 4 * MAXN * ( MAXN + 1 );
int bound, ecnt, head[MAXND + 5], to[MAXEG + 5], nxt[MAXEG + 5];
Value cst[MAXEG + 5], dist[MAXND + 5];
inline void operator () ( const int s, const int t, const Value& c ) {
#ifdef RYBY
printf ( "%d %d (%lld,%lld)\n", s, t, c.w, c.e );
#endif
to[++ecnt] = t, cst[ecnt] = c, nxt[ecnt] = head[s];
head[s] = ecnt;
to[++ecnt] = s, cst[ecnt] = c, nxt[ecnt] = head[t];
head[t] = ecnt;
}
inline Value dijkstra ( const int s, const int t ) {
static bool vis[MAXND + 5];
static std::priority_queue<PVI, std::vector<PVI>, std::greater<PVI> > heap;
for ( int i = 1; i <= bound; ++i ) vis[i] = false, dist[i] = INF;
heap.push ( { dist[s] = 0, s } );
while ( !heap.empty () ) {
PVI p ( heap.top () ); heap.pop ();
if ( vis[p.second] ) continue;
vis[p.second] = true;
for ( int i = head[p.second], v; i; i = nxt[i] ) {
if ( Value d ( p.first + cst[i] ); d < dist[v = to[i]] ) {
heap.push ( { dist[v] = d, v } );
}
}
}
return dist[t];
}
} graph;
inline int id ( const int i, const int j ) {
if ( !i || j == n ) return S;
if ( i == n || !j ) return T;
return ( i - 1 ) * ( n - 1 ) + j;
}
inline Value calc ( const LL a, const LL b ) {
coeW = a, coeE = b;
Value ret ( graph.dijkstra ( S, T ) );
#ifdef RYBY
printf ( "calc(%lld,%lld) = (%lld,%lld)\n", a, b, ret.w, ret.e );
#endif
return graph.dijkstra ( S, T );
}
inline void solve ( const Value& A, const Value& B ) {
LL a = A.e - B.e, b = B.w - A.w;
Value C ( calc ( a, b ) );
chkmin ( ans, C.w * C.e );
#ifdef RYBY
printf ( "(%lld,%lld), (%lld,%lld), (%lld,%lld)\n", A.w, A.e, C.w, C.e, B.w, B.e );
printf ( "%lld...%lld\n", ( B - A ) * ( C - A ), a * C.w + b * C.e + A.w * B.e - A.e * B.w );
#endif
if ( ( B - A ) * ( C - A ) >= 0 ) return ;
solve ( A, C ), solve ( C, B );
}
int main () {
n = rint ();
S = ( n - 1 ) * ( n - 1 ) + 1, T = S + 1;
graph.bound = ( n - 1 ) * ( n - 1 ) + 2;
for ( int i = 1; i < n; ++i ) {
for ( int j = 1; j <= n; ++j ) {
int cw = rint (), ce = rint ();
graph ( id ( i, j - 1 ), id ( i, j ), { cw, ce } );
}
}
for ( int i = 1; i <= n; ++i ) {
for ( int j = 1; j < n; ++j ) {
int rw = rint (), re = rint ();
graph ( id ( i - 1, j ), id ( i, j ), { rw, re } );
}
}
Value A ( calc ( 1, 0 ) ), B ( calc ( 0, 1 ) );
chkmin ( ans, A.w * A.e ), chkmin ( ans, B.w * B.e );
solve ( A, B );
printf ( "%lld\n", ans );
return 0;
}
\(\mathcal{Details}\)
虽然套路但毕竟是黑的,一眼秒掉好开心 owo。
Solution -「洛谷 P6158」封锁的更多相关文章
- Solution -「洛谷 P4372」Out of Sorts P
\(\mathcal{Description}\) OurOJ & 洛谷 P4372(几乎一致) 设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...
- Note/Solution -「洛谷 P5158」「模板」多项式快速插值
\(\mathcal{Description}\) Link. 给定 \(n\) 个点 \((x_i,y_i)\),求一个不超过 \(n-1\) 次的多项式 \(f(x)\),使得 \(f(x ...
- Solution -「洛谷 P4198」楼房重建
\(\mathcal{Description}\) Link. 给定点集 \(\{P_n\}\),\(P_i=(i,h_i)\),\(m\) 次修改,每次修改某个 \(h_i\),在每次修改后 ...
- Solution -「洛谷 P6577」「模板」二分图最大权完美匹配
\(\mathcal{Description}\) Link. 给定二分图 \(G=(V=X\cup Y,E)\),\(|X|=|Y|=n\),边 \((u,v)\in E\) 有权 \(w( ...
- Solution -「洛谷 P6021」洪水
\(\mathcal{Description}\) Link. 给定一棵 \(n\) 个点的带点权树,删除 \(u\) 点的代价是该点点权 \(a_u\).\(m\) 次操作: 修改单点点权. ...
- Solution -「洛谷 P4719」「模板」"动态 DP" & 动态树分治
\(\mathcal{Description}\) Link. 给定一棵 \(n\) 个结点的带权树,\(m\) 次单点点权修改,求出每次修改后的带权最大独立集. \(n,m\le10^5 ...
- Solution -「洛谷 P5236」「模板」静态仙人掌
\(\mathcal{Description}\) Link. 给定一个 \(n\) 个点 \(m\) 条边的仙人掌,\(q\) 组询问两点最短路. \(n,q\le10^4\),\(m\ ...
- Solution -「洛谷 P4320」道路相遇
\(\mathcal{Description}\) Link. 给定一个 \(n\) 个点 \(m\) 条边的连通无向图,并给出 \(q\) 个点对 \((u,v)\),询问 \(u\) 到 ...
- Solution -「洛谷 P5827」边双连通图计数
\(\mathcal{Description}\) link. 求包含 \(n\) 个点的边双连通图的个数. \(n\le10^5\). \(\mathcal{Solution}\) ...
随机推荐
- websocket 使用 spring 的service层 ,进而调用里面的 dao层 来操作数据库 ,包括redis、mysql等通用
1.前言 描述一下今天用websocket踩得坑 --->空指针异常! 我想在websocket里面使用service 层的接口,从中获取数据库的一些信息 , 使用 @Autowired 注 ...
- 移动端调试 - UC浏览器开发者版 - WIFI
Chrome 功能特性 支持PC或Pad设备,实时调试手机网页 DOM.CSS.JS调试 多功能面板满足多种调试需求 1 准备工作 保证手机与PC处于同一个无线网段. 下载Android平台的U ...
- dubbo泛化引发的生产故障之dubbo隐藏的坑
dubbo泛化引发的生产故障之dubbo隐藏的坑 上个月公司zk集群发生了一次故障,然后要求所有项目组自检有无使用Dubbo编程式/泛化调用,强制使用@Reference生成Consumer.具体原因 ...
- MySQL的innoDB存储引擎的运作方式,数据结构等
先上InnoDB架构图: 自上而下依次为内存区结构,后台线程,操作系统,磁盘存储,日志文件等. 其中内存由缓冲池,额外缓冲池,日志缓冲池组成.其中缓冲池中结构如下: 在磁盘存储文件中,MyISAM存储 ...
- FilterChain过滤器链(Servlet)
在 Web 应用中,可以部署多个 Filter,若这些 Filter 都拦截同一目标资源,则它们就组成了一个 Filter 链(也称过滤器链).过滤器链中的每个过滤器负责特定的操作和任务,客户端的请求 ...
- gin使用BasicAuth中间件
package mainimport ( "github.com/gin-gonic/gin" "net/http")// 模拟一些私人数据var secret ...
- GoLang设计模式20 - 组合模式
定义 组合模式是一种结构型设计模式. 当我们想把一组对象当做一个整体来处理时就可以考虑使用组合模式. 组合模式被视为是接口型设计模式是因为它将一组对象组装为一个树状结构.这个树状结构中的每个独立组件都 ...
- Docker 与 K8S学习笔记(二十)—— 使用Downward API向容器注入Pod信息
Kubernetes在创建Pod时,会为Pod和容器设置一些额外的信息,比如Pod名称.Pod IP.Node IP.Label.Annotation.资源限制等,我们经常会在应用程序中使用到这些数据 ...
- yum搭建私有仓库远程版
目录 一:yum安装 1.简介 1.安装 2.卸载 3.更新 4.yum安装的生命周期 二:yum搭建私有仓库(本地版) 1.下载必须的软件包(准备配置) 2.创建软件仓库 3.下载对应的软件 4.初 ...
- linux中cut命令与tr命令
目录 一:linux中cut命令 1.cut 命令作用 2.参数 3.参数案例解析: 二:tr命令 1.tr命令作用 2.tr命令格式 3.tr命令参数 4.案例解析: 一:linux中cut命令 1 ...