题目链接

题解:这道题比赛的时候,学弟说是网络流,当时看N这么大,觉得网络流没法做,实际本题通过巧妙的建图,然后离散化。

先说下建图方式,首先每个覆盖区域,只有左右端点,如果我们只用左右端点的话,最多有400个点,所以第一步离散化。每个$i$和$i+1$连一条边流量为K,费用为0的边,每一个覆盖区域从左端点$u$向右端点$v$连一条流量为1,费用为$-w$的边,因为一般算最大费用,就要把边权变成负的算最小,最后取反是最大。对了,右端点$v$要+1,因为这个覆盖区域是从$u->v$,我应该从$v+1$开始流下一个。然后源点向最左端点连一条边流量为K,费用为0的边,汇点从最右端点连条相同的边。跑费用流即可。

为什么可行呢?

首先限制了总流量为K,那么流过离散化后的每个点最大流量是K,比如下面这个例子K=3,做一条纵向切线流量最多为3,保证了答案的正确性。

#include <bits/stdc++.h>
using namespace std; const int maxn = ;
const int INF = 1e9;
int dist[maxn];
int pv[maxn],pe[maxn];
struct edge
{
int to, cap, rev;
int cost;
edge(int a, int b, int c, int d)
{
to = a, cap = b, cost = c, rev = d;
}
};
vector<edge> g[maxn];
void addedge(int from,int to,int cap,int cost)
{
g[from].push_back(edge(to,cap,cost,g[to].size()));
g[to].push_back(edge(from,,-cost,g[from].size()-));
}
int n;
int vis[maxn];
void SPFA(int s, int t)
{
for(int i = ; i < maxn; i++) dist[i] = INF;
memset(vis, , sizeof(vis));
dist[s] = , vis[s] = ;
queue<int> q;
q.push(s);
while(!q.empty())
{
int u = q.front();
q.pop();
vis[u] = ;
for(int i = ; i < g[u].size(); i++)
{
edge &e = g[u][i];
if(e.cap > && (dist[e.to] - (dist[u] + e.cost)) > )
{
pv[e.to] = u, pe[e.to] = i;
dist[e.to] = dist[u] + e.cost;
if(!vis[e.to])
{
vis[e.to] = ;
q.push(e.to);
}
}
}
}
}
int min_cost_flow(int s,int t,int f,int& max_flow)
{
int ret = 0.0;
while(f>)
{
SPFA(s, t);
if(dist[t] == INF) return ret;///同一目的地,每次增广路都是最小费用
///当所有边的流量都流净后,即没有残余网络,返回。
int d = f;
for(int v=t;v!=s;v=pv[v])
{
d = min(d,g[pv[v]][pe[v]].cap);
}
f -= d;
max_flow += d;
// printf("%d\n", ret);
ret += (int)d*dist[t]; ///走一单位就消耗dist[t]
for(int v=t;v!=s;v=pv[v])
{
edge &e = g[pv[v]][pe[v]];
e.cap -= d;
g[v][e.rev].cap += d;
}
}
return ret;
}
int u[maxn], v[maxn], w[maxn], low[maxn];
int main()
{
int T; scanf("%d", &T);
while(T--)
{
int K, M, tmpn;
scanf("%d %d %d", &tmpn, &K, &M);
int cnt = ;
for(int i = ; i <= M; i++)
{
scanf("%d %d %d", &u[i], &v[i], &w[i]);
v[i]++; ///v[i]是我所占用的,要直接流到v[i]+1
low[cnt++] = u[i];
low[cnt++] = v[i];
}
sort(low, low + cnt);
cnt = unique(low, low + cnt) - low;
for(int i = ; i <= M; i++)
{
u[i] = lower_bound(low, low + cnt, u[i]) - low;
v[i] = lower_bound(low, low + cnt, v[i]) - low;
}
for(int i = ; i <= M; i++)
{
// printf("%d %d\n", u[i], v[i]);
}
// printf("%d\n",cnt);
for(int i = ; i < cnt + ; i++) g[i].clear();
for(int i = ; i < cnt - ; i++)
{
addedge(i, i + , K, );
}
for(int i = ; i <= M; i++)
{
addedge(u[i], v[i], , -w[i]);
}
addedge(cnt + , , K, );
addedge(cnt - , cnt + , K, );
int maxflow = ;
int ans = min_cost_flow(cnt + , cnt + , INF, maxflow);
printf("%d\n", -ans);
}
return ;
}

Code

焦作F Modular Production Line 费用流的更多相关文章

  1. ACM-ICPC 2018 焦作赛区网络预赛 F. Modular Production Line (区间K覆盖-最小费用流)

    很明显的区间K覆盖模型,用费用流求解.只是这题N可达1e5,需要将点离散化. 建模方式步骤: 1.对权值为w的区间[u,v],加边id(u)->id(v+1),容量为1,费用为-w; 2.对所有 ...

  2. 【网络流】Modular Production Line

    [网络流]Modular Production Line 焦作上的一道,网络流24题中的原题.... https://nanti.jisuanke.com/t/31715 给出了1e5个点,但是因为最 ...

  3. Modular Production Line

     Modular Production Line 时空限制: 1000ms /65536K   An automobile factory has a car production line. Now ...

  4. Modular Production Line (MCMF)

    Modular Production Line \[ Time Limit: 1000ms\quad Memory Limit: 65536kB \] 题意 给出 \(N\) 种零件,现在你可以用连续 ...

  5. BZOJ 2424 DP OR 费用流

    思路: 1.DP f[i][j]表示第i个月的月底 还剩j的容量 转移还是相对比较好想的-- f[i][j+1]=min(f[i][j+1],f[i][j]+d[i]); if(j>=u[i+1 ...

  6. 图论-zkw费用流

    图论-zkw费用流 模板 这是一个求最小费用最大流的算法,因为发明者是神仙zkw,所以叫zkw费用流(就是zkw线段树那个zkw).有些时候比EK快,有些时候慢一些,没有比普通费用流算法更难,所以学z ...

  7. POJ2195 Going Home[费用流|二分图最大权匹配]

    Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22088   Accepted: 11155 Desc ...

  8. 【BZOJ-3638&3272&3267&3502】k-Maximum Subsequence Sum 费用流构图 + 线段树手动增广

    3638: Cf172 k-Maximum Subsequence Sum Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 174  Solved: 9 ...

  9. UVa 2197 & 拆点分环费用流

    题意: 给你一个带权有向图,选择一些边组成许多没有公共边的环,使每个点都在k个环上,要求代价最小. SOL: 现在已经养成了这种习惯,偏题怪题都往网络流上想... 怎么做这题呢... 对我们看到每个点 ...

随机推荐

  1. Ansible的使用和模块化深入

    Ansible配置 配置文件:/etc/ansible/ansible.cfg [default] 默认配置 inventory = /etc/ansible/hosts主机清单 library = ...

  2. NodeJS基础入门-fs文件系统

    文件I/O是由简单封装的标准POSIX函数提供.通过require('fs') 使用该模块.所有的方法都有异步和同步的形式. 异步方法的最后一个参数都是一个回调函数.传给回调函数的参数取决于具体方法, ...

  3. linux 下 docker-compose安装

    docker和dockers-compose的版本兼容对照 以下是我的服务器的相关信息 linux版本 [root@izbp16fm097gaw3tdaog2wz bin]# cat /proc/ve ...

  4. python 类的封装/property类型/和对象的绑定与非绑定方法

    目录 类的封装 类的property特性 类与对象的绑定方法与非绑定方法 类的封装 封装: 就是打包,封起来,装起来,把你丢进袋子里,然后用绳子把袋子绑紧,你还能拿到袋子里的那个人吗? 1.隐藏属性和 ...

  5. Erasing and Winning UVA - 11491 贪心

    题目:题目链接 思路:不难发现,要使整体尽量大,应先满足高位尽量大,按这个思路优先满足高位即可 AC代码: #include <iostream> #include <cstdio& ...

  6. 带权并查集:HDU3172-Virtual Friends

    Virtual Friends Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot ...

  7. Linux学习-逻辑滚动条管理员 (Logical Volume Manager)

    LVM 可以整合多个实体 partition 在一起, 让这些 partitions 看起来就像是一个磁盘一样!而且,还可以在未来新增或移除其他的实 体 partition 到这个 LVM 管理的磁盘 ...

  8. 15年多校第一场七题hdu5294

    要做这题,先要明白图的割,说白了就是 为了让原点无法到汇点要删几条边(之所以叫割,就是在图面上切一刀,减掉最小的边是原点和汇点成为两个集合),想到了割先放着一会用. 题中说只有沿最短路走才有可能追上, ...

  9. loj2028 「SHOI2016」随机序列

    定义区间是内部只含有乘号的区间. 对于区间左端点是 \(l \geq 2\) 的情况,左端点前头是加号的情况和前头是减号的情况的个数是相同的.因此这些区间不对答案产生贡献. 所以区间左端点必定是 \( ...

  10. luogu3370 【模板】字符串哈希

    #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> ...