2020牛客暑期多校训练营(第一场)H Minimum-cost Flow
题目:给n个点,m条边。接下来m行包含(a,b,c),即a,b之间有单位流量代价为c的边。接下来有q个问题,每个问题给定(x,y),即假设每条边的容量为x/y时,从点1到点n流1单位的流量,最少的花费是多少,如果无法从点1到点n流1单位的流量则输出“NaN”。
思路:首先我们需要想到一个结论,每条边最多只能使用一次,这个自己比划一下就可以,其中包含贪心的想法。得到这个结论后,我们发现整张图就变成了流量为1的网络流。然后,根据(x,y)说明我们至少需要 y / x + (y % x != 0)条从1到n的最少花费路径,这个我们可以通过最小费用流预处理得到所有能够得到的最小花费路径,并记录每条路径的最小花费。这样,对于每个询问(x,y),我们只需要取前y / x小的边,如果y % x != 0,则从后面的边补充一些即可。

补充:为什么我们可以直接这样直接取路径,看上图,我们得到的最小花费应该是两个:3,21。这是懂得网络流算法都能看出的,如果我们有组询问(2,3),我们可以得到答案应该是ans = 3 * 2/3 + 21 * 1/3 = 9。但这两条路分别是1->2->3->4和1->3->2->4得到的,会感觉有点奇怪“这样就是答案”。其实我们需要回到网络流的反向边在算法中的用途"反流"和正向边可以把"反流"失去的流量再"补流",下面附一个来体现ans = 9是怎么得到的,然后思考。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <cstring> using namespace std; #define ll long long
#define pb push_back
#define fi first
#define se second const int N = ;
const int M = ;
const int INF = 1e9 + 7e8;
struct edge
{
int to, nxt, cap, flow, w;
}e[M << ];
int head[N], d[N], vis[N], pre[N];
queue<int > que;
int a[N], b[N];
int n, m, tot, s, t, cnt; inline void add(int u, int v, int w)
{
e[tot].to = v; e[tot].w = w; e[tot].cap = ;
e[tot].flow = ; e[tot].nxt = head[u]; head[u] = tot++;
e[tot].to = u; e[tot].w = -w; e[tot].cap = ;
e[tot].flow = ; e[tot].nxt = head[v]; head[v] = tot++;
} bool spfa()
{
for(int i = ; i <= n; ++i) d[i] = INF, vis[i] = false, pre[i] = -;
while(!que.empty()) que.pop();
d[s] = ; vis[s] = true; pre[s] = -;
que.push(s);
//printf("s = %d t = %d\n", s, t);
while(!que.empty()){
int now = que.front();
que.pop();
vis[now] = false; for(int o = head[now]; ~o; o = e[o].nxt){
if(e[o].cap - e[o].flow && d[e[o].to] > d[now] + e[o].w){
d[e[o].to] = d[now] + e[o].w;
pre[e[o].to] = o;
if(!vis[e[o].to]){
vis[e[o].to] = true;
que.push(e[o].to);
}
}
}
}
if(pre[t] == -) return false;
else return true;
} void mcmf()
{
while(spfa()){
int _min = INF;
for(int o = pre[t]; ~o; o = pre[e[o ^ ].to]){
_min = min(_min, e[o].cap - e[o].flow);
}
for(int o = pre[t]; ~o; o = pre[e[o ^ ].to]){
e[o].flow += _min;
e[o ^ ].flow -= _min;
}
//cout << _min << endl;
//cout << "dis = " << d[t] << endl;
a[++cnt] = d[t];
//cout << "d = " << d[t] << endl;
}
for(int i = ; i <= cnt; ++i) a[i] += a[i - ];
} ll GCD(ll a, ll b)
{
return b == ? a : GCD(b, a % b);
} void solve()
{
while(~scanf("%d%d", &n, &m)){
cnt = ;
for(int i = ; i <= n; ++i) head[i] = -; tot = ;
int x, y, w;
for(int i = ; i <= m; ++i){
scanf("%d%d%d", &x, &y, &w);
add(x, y, w);
}
s = ; t = n;
mcmf(); int q;
scanf("%d", &q);
while(q--){
int x, y;
scanf("%d%d", &x, &y);
if(x == ){
puts("NaN");
continue;
}
int gcd = GCD(x, y);
y /= gcd; x /= gcd; int need = y / x + (y % x != );
if(need > cnt){
puts("NaN");
continue;
} need = y / x;
ll up = (ll)a[need] * x;
ll down = y;
int remains = y % x;
up += (ll)(a[need + ] - a[need]) * remains;
gcd = GCD(up, down);
up /= gcd; down /= gcd;
printf("%lld/%lld\n", up, down);
}
}
} int main(){ solve(); return ;
}
2020牛客暑期多校训练营(第一场)H Minimum-cost Flow的更多相关文章
- 2020牛客暑期多校训练营 第二场 K Keyboard Free 积分 期望 数学
LINK:Keyboard Free 我要是会正经的做法 就有鬼了. 我的数学水平没那么高. 三个同心圆 三个动点 求围成三角形面积的期望. 不会告辞. 其实可以\(n^2\)枚举角度然后算出面积 近 ...
- 2020牛客暑期多校训练营 第二场 J Just Shuffle 置换 群论
LINK:Just Shuffle 比较怂群论 因为没怎么学过 置换也是刚理解. 这道题是 已知一个置换\(A\)求一个置换P 两个置换的关键为\(P^k=A\) 且k是一个大质数. 做法是李指导教我 ...
- 2020牛客暑期多校训练营 第二场 I Interval 最大流 最小割 平面图对偶图转最短路
LINK:Interval 赛时连题目都没看. 观察n的范围不大不小 而且建图明显 考虑跑最大流最小割. 图有点稠密dinic不太行. 一个常见的trick就是对偶图转最短路. 建图有点复杂 不过建完 ...
- 2020牛客暑期多校训练营 第二场 C Cover the Tree 构造 贪心
LINK:Cover the Tree 最受挫的是这道题,以为很简单 当时什么都想不清楚. 先胡了一个树的直径乱搞的贪心 一直过不去.后来意识到这类似于最经典长链剖分优化贪心的做法 然后那个是求最大值 ...
- 2020牛客暑期多校训练营 第二场 B Boundary 计算几何 圆 已知三点求圆心
LINK:Boundary 计算几何确实是弱项 因为好多东西都不太会求 没有到很精通的地步. 做法很多,先说官方题解 其实就是枚举一个点 P 然后可以发现 再枚举一个点 然后再判断有多少个点在圆上显然 ...
- 2020牛客暑期多校训练营 第二场 A All with Pairs 字符串hash KMP
LINK:All with Pairs 那天下午打这个东西的时候状态极差 推这个东西都推了1个多小时 (比赛是中午考试的我很困 没睡觉直接开肝果然不爽 一开始看错匹配的位置了 以为是\(1-l\)和\ ...
- 2020牛客暑假多校训练营 第二场 H Happy Triangle set 线段树 分类讨论
LINK:Happy Triangle 这道题很容易. 容易想到 a+b<x a<x<b x<a<b 其中等于的情况在第一个和第三个之中判一下即可. 前面两个容易想到se ...
- 2020牛客暑期多校训练营(第一场)Easy Integration
传送门:J. Easy Integration 题意:给你n,求这个积分,最后的结果分子是记为p,分母记为q. 求(p*q-1)mod 998244353. 题解:比赛完看到巨巨说这是贝塔函数,我一搜 ...
- 2020牛客暑期多校训练营(第四场)BCFH
BCFH B. Basic God Problem 题意 给出c和n,求fc(n). 题解 递归到最后 fc 函数肯定等于1,那么就变成了求c被乘了几次,只要找到 x 最多能被分解成多少个数相乘就好了 ...
随机推荐
- sorted排序
sorted(['bob', 'about', 'Zoo', 'Credit']) # ['Credit', 'Zoo', 'about', 'bob'] ''' 默认情况下,对字符串排序,是按照AS ...
- C++ Primer Plus(一)
完整阅读C++ Primer Plus 系统重新学习C++语言部分,记录重要但易被忽略的,关键但易被遗忘的. 预备 1.C++相对于C增加了最关键的两项,面向对象和范型编程. 处理数据 2.对于变量明 ...
- 搜索引擎ElasticSearch入门
前言 最近项目上需要用到搜索引擎,由于之前自己没有了解过,所以整理了一下搜索引擎的相关概念知识. 正文 想查数据就免不了搜索,搜索就离不开搜索引擎,百度.谷歌都是一个非常庞大复杂的搜索引擎,他们几乎索 ...
- MySql数据库GROUP BY使用过程中的那些坑
MySql数据库GROUP BY使用过程中的那些坑 GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组. 特别注意: group by 有一个原则,就是 select 后面的所有 ...
- java基础-java与c#接口不同点
1.接口中定义成员 C#,如图我在接口ITest添加了一个字段n,那么vs直接就显示红色的底线,而错误就是接口不能包含字段 java,如下图,编译也是报错但是并不是接口中不能包含而是缺少赋值,那么我们 ...
- 【Spring注解驱动开发】关于BeanPostProcessor后置处理器,你了解多少?
写在前面 有些小伙伴问我,学习Spring是不是不用学习到这么细节的程度啊?感觉这些细节的部分在实际工作中使用不到啊,我到底需不需要学习到这么细节的程度呢?我的答案是:有必要学习到这么细节的程度,而且 ...
- 计算机网络之tcp三次握手
客户端与服务器之间数据的发送和返回的过程当中需要创建一个叫TCP connection的东西:由于TCP不存在连接的概念,只存在请求和响应,请求和响应都是数据包,它们之间都是经过由TCP创建的一个从客 ...
- Elastic认证考试,请先看这一篇
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/wojiushiwo987/article ...
- Postman之API测试使用全指南
Postman Postman是一个可扩展的API开发和测试协同平台工具,可以快速集成到CI/CD管道中.旨在简化测试和开发中的API工作流. Postman 工具有 Chrome 扩展和独立客户端, ...
- 二.1.vue-开发环境搭建
一vue开发环境搭建 1.下载二进制包 https://nodejs.org/zh-cn/ 直接下一步下一步即可,然后dmd中如下显示说明成功: C:\Program Files\nodejs> ...