「SNOI2019」通信 分治优化费用流建图
题意:
n 个排成一列的哨站要进行通信。第 i 个哨站的频段为 ai。
每个哨站 ii 需要选择以下二者之一:
1.直接连接到控制中心,代价为 W;
2.连接到前面的某个哨站 j(j<i),代价为 |ai−aj|。 每个哨站只能被后面的至多一个哨站连接。
请你求出最小可能的代价和。
题解:
显然的费用流
然后我耿直的n^2建边,觉得我的费用流很快,应该可以过
然后返回了TLE
然后google了一下题解:发现这题卡了n^2建图,需要优化建边
我这里是通过分治优化的
就是类似与建立一个虚点
一个x要向y的一个前缀建图,所以就可以类似前缀和优化建图那样,
按权值排序然后建出一条链,链上两个点之间的流量为INF,费用为权值之差,然后每个点向对应的点连边
但这样建图是错误的,原因在于我们把点排了序,改变了编号顺序,
所以一个点能到达的点不一定是它可以到达的
所以我们要固定在固定编号顺序的情况下这样连边,也就是说x的一个区间和y的一个区间之间这样连边,
要求两个区间不重合,且x的区间比y的区间小
那么很容易想到分治建图,每次让[l,mid]向[mid+1,r]连边,剩下的递归下去就行了
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map> #define pi acos(-1.0)
#define eps 1e-9
#define fi first
#define se second
#define rtl rt << 1
#define rtr rt << 1 | 1
#define bug printf("******\n")
#define mem(a, b) memset(a, b, sizeof(a))
#define name2str(x) #x
#define fuck(x) cout << #x " = " << x << endl
#define sfi(a) scanf("%d", &a)
#define sffi(a, b) scanf("%d %d", &a, &b)
#define sfffi(a, b, c) scanf("%d %d %d", &a, &b, &c)
#define sffffi(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d)
#define sfL(a) scanf("%lld", &a)
#define sffL(a, b) scanf("%lld %lld", &a, &b)
#define sfffL(a, b, c) scanf("%lld %lld %lld", &a, &b, &c)
#define sffffL(a, b, c, d) scanf("%lld %lld %lld %lld", &a, &b, &c, &d)
#define sfs(a) scanf("%s", a)
#define sffs(a, b) scanf("%s %s", a, b)
#define sfffs(a, b, c) scanf("%s %s %s", a, b, c)
#define sffffs(a, b, c, d) scanf("%s %s %s %s", a, b, c, d)
#define FIN freopen("../in.txt", "r", stdin)
#define gcd(a, b) __gcd(a, b)
#define lowbit(x) x & -x
#define IO iOS::sync_with_stdio(false) using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const ULL seed = ;
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = 1e6 + ;
const int maxm = 8e6 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ; struct Cost_MaxFlow {
int s, t, tot, maxflow, head[maxn], vis[maxn], pre[maxn], last[maxn];
LL mincost, maxcost, dis[maxn], disf[maxn];
struct Edge {
int v, w, nxt;
int cost;
} edge[maxm];
queue<int> q; void init() {
tot = ;
mincost = maxcost = ;
memset(head, -, sizeof(head));
} void add(int u, int v, int f, int e) {
edge[++tot].v = v, edge[tot].nxt = head[u], head[u] = tot, edge[tot].w = f, edge[tot].cost = e;
edge[++tot].v = u, edge[tot].nxt = head[v], head[v] = tot, edge[tot].w = , edge[tot].cost = -e;
} bool spfa_max() {
memset(dis, 0xef, sizeof(dis));
q.push(s), dis[s] = , disf[s] = INFLL, pre[t] = -;
while (!q.empty()) {
int u = q.front();
q.pop();
vis[u] = ;
for (int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if (edge[i].w && dis[v] < dis[u] + edge[i].cost) {
dis[v] = dis[u] + edge[i].cost, last[v] = i, pre[v] = u;
disf[v] = min(disf[u], 1LL * edge[i].w);
if (!vis[v])
vis[v] = , q.push(v);
}
}
}
return ~pre[t];
} void dinic_max() {
while (spfa_max()) {
int u = t;
maxflow += disf[t];
maxcost += disf[t] * dis[t];
while (u != s) {
edge[last[u]].w -= disf[t];
edge[last[u] ^ ].w += disf[t];
u = pre[u];
}
}
} bool spfa_min() {
memset(dis, 0x3f, sizeof(dis));
memset(vis, , sizeof(vis));
memset(disf, 0x3f, sizeof(disf));
q.push(s), dis[s] = , vis[s] = , pre[t] = -;
while (!q.empty()) {
int u = q.front();
q.pop();
vis[u] = ;
for (int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if (edge[i].w > && dis[v] > dis[u] + edge[i].cost) {
dis[v] = dis[u] + edge[i].cost, pre[v] = u;
last[v] = i, disf[v] = min(disf[u], 1LL * edge[i].w);
if (!vis[v])
vis[v] = , q.push(v);
}
}
}
return pre[t] != -;
} void dinic_min() {
while (spfa_min()) {
int u = t;
maxflow += disf[t];
mincost += disf[t] * dis[t];
while (u != s) {
edge[last[u]].w -= disf[t];
edge[last[u] ^ ].w += disf[t];
u = pre[u];
}
}
}
} F; int n, W, a[maxn], cnt[maxn], sum; void link(int L, int R) {
if (L == R) return;
int num = , mid = (L + R) / ;
for (int i = L; i <= R; i++) cnt[++num] = a[i];
sort(cnt + , cnt + + num);
num = unique(cnt + , cnt + + num) - cnt - ;
for (int i = ; i < num; i++) {
F.add(sum + i, sum + i + , INF, cnt[i + ] - cnt[i]);
F.add(sum + i + , sum + i, INF, cnt[i + ] - cnt[i]);
}
for (int i = L; i <= R; i++) {
if (i <= mid) {
int pos = lower_bound(cnt + , cnt + + num, a[i]) - cnt;
F.add(sum + pos, i + n, , );
} else {
int pos = lower_bound(cnt + , cnt + + num, a[i]) - cnt;
F.add(i, sum + pos, , );
}
}
sum += num;
link(L, mid), link(mid + , R);
} int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
while (~sffi(n, W)) {
for (int i = ; i <= n; i++) sfi(a[i]);
F.init();
F.s = , F.t = * n + ;
sum = * n + ;
for (int i = ; i <= n; i++) {
F.add(F.s, i, , );
F.add(i + n, F.t, , );
F.add(i, F.t, , W);
}
link(, n);
F.dinic_min();
printf("%lld\n", F.mincost);
}
#ifndef ONLINE_JUDGE
cout << "Totle Time : " << (double) clock() / CLOCKS_PER_SEC << "s" << endl;
#endif
return ;
}
「SNOI2019」通信 分治优化费用流建图的更多相关文章
- 「SNOI2019」通信 分治建图
根据题意 每个点可以直接与S,T相连 也可以和前面的哨站相连 暴力建边的话 有n2条边 要用分治优化建边: 类似于归并排序 先对每一层分为左半边与右半边 对每一半都拿出来先排序去重后 直接排成一条链建 ...
- 【LOJ】#3097. 「SNOI2019」通信
LOJ#3097. 「SNOI2019」通信 费用流,有点玄妙 显然按照最小路径覆盖那题的建图思路,把一个点拆成两种点,一种是从这个点出去,标成\(x_{i}\),一种是输入到这个点,使得两条路径合成 ...
- 「SNOI2019」通信
题目 还好我没生在陕西啊 首先发现这个题不能\(dp\),数据范围不大,好像一种网络流的样子啊 哎等等,这样向后面连边不是一个\(DAG\)吗,这不是最小权路径覆盖的板子吗 于是我们套路的拆点,对于一 ...
- Codeforces 362E Petya and Pipes 费用流建图
题意: 给一个网络中某些边增加容量,增加的总和最大为K,使得最大流最大. 费用流:在某条边增加单位流量的费用. 那么就可以2个点之间建2条边,第一条给定边(u,v,x,0)这条边费用为0 同时另一条边 ...
- POJ2516K次费用流建图
Description: N个订单(每个订单订K种商品),M个供应商(每个供应商供应K种商品),K种商品,后N行,表示每一个订单的详细信息,后M行表示每个供应商供应的详细信息,后K 个N * M的矩阵 ...
- HDU 6611 K Subsequence(Dijkstra优化费用流 模板)题解
题意: 有\(n\)个数\(a_1\cdots a_n\),现要你给出\(k\)个不相交的非降子序列,使得和最大. 思路: 费用流建图,每个点拆点,费用为\(-a[i]\),然后和源点连边,和后面非降 ...
- hdu4411 经典费用里建图
题意: 给以一个无向图,0 - n,警察在0,他们有k个警队,要派一些警队去1--n个城市抓小偷, 问所有吧所有小偷全抓到然后在返回0的最小路径和是多少,当地i个城市被攻击的时候他会通知i ...
- 【LOJ】#3098. 「SNOI2019」纸牌
LOJ#3098. 「SNOI2019」纸牌 显然选三个以上的连续牌可以把他们拆分成三个三张相等的 于是可以压\((j,k)\)为有\(j\)个连续两个的,有\(k\)个连续一个的 如果当前有\(i\ ...
- Loj #3096. 「SNOI2019」数论
Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...
随机推荐
- 防止重复提交 aspx.net
:服务器控制.后台生成一个token,存入session或者其他缓存里面.渲染表单时,给form一个隐藏的token(令牌).用户提交表单时:先判断表单里面的token是否存在,不存在拒绝接受此数据: ...
- Linux部分常用命令详解(二)
date 命令详解 date命令可以按照指定格式显示日期,只键入date则以默认格式显示当前时间 例如: 如果需要以指定的格式显示日期,可以使用“+”开头的字符串指定其格式,详细格式如下: %n : ...
- POJ 1052 MPI Maelstrom
MPI Maelstrom Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 5547 Accepted: 3458 Des ...
- fastjson转换包含date类型属性的对象时报错com.alibaba.fastjson.JSONException: For input string: "13:02:19"
问题:time类型数据插入不进mysql数据库:调试的时候报如下错误: Caused by: java.lang.NumberFormatException: For input string: &q ...
- BZOJ 4289 最短路+优化建图
题意:给出一个N个点M条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点1到点N的最小代价.起点的代价是离开起点的边的边权,终点的代价是进入终点的边的边权. 解法:参考h ...
- day06 python is == 编码 解码
day06 python 一. is 和 == 的区别 == :比较, 判断, 比较的是值: 可以比较数字, 字符串, 列表, 元组, 字典,等 is :是 比较, 比较的是内存地 ...
- Fabric.js的使用
最近项目有一个绘制的功能,搜了一圈发现fabric.js口碑不错,但是文档稀缺,于是东看看西搜搜的把项目的需求都给实现了,想分享一下. 篇幅有点长,但看完后可以轻松驾驭fabric.我的项目是基于VU ...
- SpringCloud---分布式服务跟踪---Spring Cloud Sleuth
1.概述 1.1 为什么要用到服务跟踪? 随着业务的发展,系统规模也会变得越来越大,各服务之间的调用关系也变得越来越错综复杂: 通常一个由客户端发起的请求 在后端系统中会经过多个不同的微服务调用 ...
- Delphi ResourceString的用法
在Delphi编程的那段“古老”的日子里(就是在版本4之前),在程序中使用字符串有两个基本的方法.你可以使用字符串将它们嵌入到源程序中,例如: MessageDlg( 'Leave your stin ...
- 中位数+暴力——cf433C
/* 中位数到所有数的距离之和最小 因为只能改一个数,所以我们找一个数,将其改为和其相邻的数的中位数,使答案最小 先求一次原答案 把每个数相邻的数用vector存下来,然后排序找中位数,计算减小的量 ...