Codeforces 1045. A. Last chance(网络流 + 线段树优化建边)

题意

给你 \(n\) 个武器,\(m\) 个敌人,问你最多消灭多少个敌人,并输出方案。

总共有三种武器。

  • SQL 火箭 - 能消灭给你集合中的一个敌人 \(\sum |S| \le 100000\)
  • 认知光束 - 可以消灭 \([l, r]\) 区间中的一个敌人;
  • OMG 火箭筒 - 消灭给你集合中的 \(0\) 个或者 \(2\) 个敌人,集合大小为 \(3\) ,且火箭筒消灭的集合互不重合。

\(n, m \le 5000\)

题解

现场的时候直觉告诉我是网络流,但是这个数据范围,以及 CodeForces 从不出网络流的传言,不敢刚。。

其实这题还是个网络流,因为可以看出来还是个是个二分图求最大匹配的模型(对于前两种武器来说)。

首先对于第一种武器,可以直接在二分图上暴力连边。

第二种武器,我们可以考虑线段树优化建边就行了。(就是树上的边从父亲向儿子连 \(inf\) 就行了)

第三种武器,看起来只有 \(0,2\) 两种取值很奇怪,其实我们可以把它当成有 \(0,1,2\) 三种取值。

也就是说这个点可以匹配 \(0\sim 2\) 个点。

为什么取 \(1\) 时候是对的呢?因为我们总可以在集合中找另外一个点,把原来消灭它的武器换成这个武器就行了。

然后就可以建完了,至于时间复杂度 ,题解给了一个 \(O(nm \log m)\) 的复杂度,其实我觉得是 \(O(flow)\) 。。


然后输出方案有些麻烦,首先考虑前两种武器,第一种武器可以直接先匹配,第二种武器我们在线段树上自底向上依次分配可行的节点就行了,这个用一个 std :: vector 作为递归函数返回值返回值比较好写。

然后考虑第三种武器,只需要对于 \(flow = 1\) 的情况再找一个匹配了的点,替换消灭的武器就行了。

总结

然后对于一些无法取值的流量,我们可以考虑先取,然后通过构造使得这个流量满足条件。

网络流输出方案的时候考虑退流会退到最开始的哪个地方就行了。

代码

#include <bits/stdc++.h>#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << (x) << endl
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#define All(x) (x).begin(), (x).end()using namespace std;template<typename T> inline bool chkmin(T &a, T b) {return b < a ? a = b, 1 : 0;}
template<typename T> inline bool chkmax(T &a, T b) {return b > a ? a = b, 1 : 0;}inline int read() {int x(0), sgn(1); char ch(getchar());for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1;for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48);return x * sgn;
}void File() {
#ifdef zjp_shadowfreopen ("a.in", "r", stdin);freopen ("a.out", "w", stdout);
#endif
}int n, m;const int inf = 0x3f3f3f3f;template<int Maxn, int Maxm>
struct Dinic {int Head[Maxn], Next[Maxm], cap[Maxm], to[Maxm], e;Dinic() { e = 1; }inline void add_edge(int u, int v, int flow) {to[++ e] = v; Next[e] = Head[u]; Head[u] = e; cap[e] = flow;}inline void Add(int u, int v, int flow) {add_edge(u, v, flow); add_edge(v, u, 0);}int S, T, dis[Maxn];bool Bfs() {queue<int> Q; Q.push(S); Set(dis, 0); dis[S] = 1;while (!Q.empty()) {int u = Q.front(); Q.pop();for (int i = Head[u], v = to[i]; i; v = to[i = Next[i]])if (cap[i] && !dis[v]) dis[v] = dis[u] + 1, Q.push(v);}return dis[T];}int cur[Maxn];int Dfs(int u, int flow) {if (u == T || !flow) return flow;int res = 0, f;for (int &i = cur[u]; i; i = Next[i]) {int v = to[i];if (dis[v] == dis[u] + 1 && (f = Dfs(v, min(flow, cap[i])))) {cap[i] -= f, cap[i ^ 1] += f, res += f;if (!(flow -= f)) break;}}if (!res) dis[u] = 0;return res;}int Run() {int sum_flow = 0;while (Bfs())Cpy(cur, Head), sum_flow += Dfs(S, inf);return sum_flow;}};const int N = 5050;Dinic<(int)1e5, (int)4e5> D;int tot;#define lson o << 1, l, mid
#define rson o << 1 | 1, mid + 1, r#define Travel(i, u, v) for(int i = D.Head[u], v = D.to[i]; i; v = D.to[i = D.Next[i]])int ans[N], Bef;template<int Maxn>
struct Segment_Tree {int id[Maxn];void Build(int o, int l, int r) {if (l == r) { id[o] = l; return ; }id[o] = ++ tot;int mid = (l + r) >> 1;Build(lson); Build(rson);D.Add(id[o], id[o << 1], id[o << 1] <= m ? 1 : inf);D.Add(id[o], id[o << 1 | 1], id[o << 1 | 1] <= m ? 1 : inf);}inline void Connect(int o, int l, int r, int ql, int qr, int Id) {if (ql <= l && r <= qr) { D.Add(Id, id[o], 1); return ; }int mid = (l + r) >> 1;if (ql <= mid) Connect(lson, ql, qr, Id);if (qr > mid) Connect(rson, ql, qr, Id);}vector<int> find(int o, int l, int r) {if (l == r) return vector<int>();vector<int> tmp;int mid = (l + r) >> 1;vector<int> ls = find(lson), rs = find(rson);set_union(All(ls), All(rs), inserter(tmp, tmp.end()));Travel(i, id[o], v)if (v <= m && !D.cap[i]) tmp.push_back(v);Travel(i, id[o], v) if (D.cap[i] && v > Bef) {int cur = tmp[tmp.size() - 1]; tmp.pop_back();ans[cur] = v - Bef;}return tmp;}};Segment_Tree<N << 2> T;vector<int> V1, V2, V3;int Ref[N], from[N], go[N];void Get_Ans() {for (int u : V1) {Travel(i, Ref[u], v)if (v <= m && D.cap[i ^ 1]) ans[v] = u;}T.find(1, 1, m);for (int u : V3) {int flow = D.cap[from[u]];Travel(i, Ref[u], v)if (v != D.S && !D.cap[i]) ans[v] = u;if (flow == 1)Travel(i, Ref[u], v)if (v != D.S && D.cap[i]) { ans[v] = u; break; }}
}int main () {File();n = read(), m = read();tot = m; T.Build(1, 1, m); Bef = tot;D.S = tot + n + 1; D.T = tot + n + 2;For (i, 1, m) D.Add(i, D.T, 1), go[i] = D.e - 1;For (i, 1, n) {int opt = read();D.Add(D.S, Ref[i] = ++ tot, 1 + (opt == 2)); from[i] = D.e - 1;if (opt == 0) {int k = read(); V1.push_back(i);while (k --) D.Add(tot, read(), 1);} else if (opt == 1) {int l = read(), r = read(); V1.push_back(i);T.Connect(1, 1, m, l, r, tot);} else {int a = read(), b = read(), c = read();V3.push_back(i);D.Add(tot, a, 1);D.Add(tot, b, 1);D.Add(tot, c, 1);}}printf ("%d\n", D.Run());Get_Ans();For (i, 1, m) if (ans[i])printf ("%d %d\n", ans[i], i);return 0;}

转载于:https://www.cnblogs.com/zjp-shadow/p/9700362.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/451196.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常用宏定义 - 系统相关

/** 是否iPad */ #define isPad (UI_USER_INTERFACE_IDIOM() UIUserInterfaceIdiomPad)/** 是否iPad */ #define someThing (UI_USER_INTERFACE_IDIOM() UIUserInterfaceIdiomPad)? ipad: iphone/** 获取系统版本 */ #define IOS_VERSION &#xff3b;[UIDevice currentDevi…

周鸿祎详解360手机战略:赚钱不靠硬件靠服务

摘要&#xff1a;奇虎360总裁周鸿祎不久前在微博上宣布360公司将要进军手机行业的消息后&#xff0c;一度掀起业界的轩然大波&#xff0c;褒贬之声均不绝于耳。对于合作厂商的选择&#xff0c;周鸿祎直言出货量是一个重要参考指标&#xff0c;“每年的出货量最少不低于500万~10…

解决报错:;Syntax error on token(s), misplaced construct(s)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 报错如题&#xff0c;这是语法错误&#xff0c;如括号不匹配、代码没有写在一个方法中、少分号、变量名不对、少半个大括号 ... 总之就…

java移位运算符

java中有三种移位运算符 << : 左移运算符&#xff0c;num << 1 相当于num乘以2 >> : 右移运算符&#xff0c;num >> 1 相当于num除以2 >>> : 无符号右移&#xff0c;忽略符号位&#xff0c;空位都以0补齐…

在页面上显示PDF

/// <summary>/// 读取PDF文件/// </summary>/// <param name"fName">文件名称(可以从其他地方传进来)</param>/// <returns></returns>public FileStreamResult readPDF(string fName "pdf文件.pdf"){string dirp …

7.15模拟赛

T1.fuction 吐槽一波错误拼写。 跟考场思路差不多&#xff0c;只不过细节挺多的呢。 判掉a0,b0,c0的几种组合&#xff0c;还有负数的情况要打标记特殊处理。 然后就是一个拓欧啦&#xff0c;先求出ggcd(a,b)&#xff0c;顺便求出axbyg的x和y&#xff0c;然后根据裴蜀定理&#…

苏宁国美盈利报警:线下乏力线上重金加码

摘要&#xff1a;国美电器则发布盈利预警&#xff0c;预计今年一季度净利润同比大幅减少———这也致使国美股价最近连续低位徘徊。苏宁电器一季报显示&#xff0c;今年1至3月公司营业收入226 .41亿元&#xff0c;同比增长10%&#xff0c;但盈利9.51亿元&#xff0c;同比下降15…

WebService到底是什么?

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 一、序言 大家或多或少都听过WebService&#xff08;Web服务&#xff09;&#xff0c;有一段时间很多计算机期刊、书籍和网站都大肆的提…

JAVA中PO,VO,DTO,BO,DAO,POJO解释

&#xff08;一&#xff09;VO与PO ORM是Object Relational Mapping&#xff08;对象关系映射&#xff09;的缩写。通俗点讲&#xff0c;就是将对象与关系数据库绑定&#xff0c;用对象来表示关系数据。在O/R Mapping的世界里&#xff0c;有两个基本的也是重要的东东需要了解&…

互掐盗播风云再起 三大视频网站存和解可能

摘要&#xff1a;近期&#xff0c;视频网站互掐盗播风云再起。腾讯视频已于5月13日向PPS开炮&#xff0c;宣称PPS盗播其五部独家剧&#xff1b;5月14日&#xff0c;搜狐视频亦指责PPS盗播其23部热播剧。面对这两家的连续开炮&#xff0c;PPS方面也进行了相应的回应&#xff0c;…

springboot和quartz整合实现动态定时任务(持久化单节点)

Quartz是一个完全由java编写的开源作业调度框架,为在Java应用程序中进行作业调度提供了简单却强大的机制&#xff0c;它支持定时任务持久化到数据库&#xff0c;从而避免了重启服务器时任务丢失&#xff0c;支持分布式多节点&#xff0c;大大的提高了单节点定时任务的容错性。s…

JAVA中protected的作用

类NewObject中有protected修饰的方法或者属性&#xff0c;则&#xff1a; 同一个包中&#xff1a; 可在同一个包里的子类中实例化NewObject类获得对象&#xff0c;然后可用该对象访问protected修饰的方法或者属性&#xff0c;即.操作访问。可在同一个包里的非子类中实例化NewOb…

wsimport 不是内部或外部命令,也不是可运行的程序或批处理文件

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 今天使用wsimport生成webservice client端代码&#xff0c;wsimport提示不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件…

静态变量的多线程同步问题

2019独角兽企业重金招聘Python工程师标准>>> 我们先来讨论一个问题&#xff0c;一个类的静态变量当类被多次实例化的时候&#xff0c;静态变量是否会受影响&#xff1f;首先我们应该清楚的是静态变量是在类被JVM classloader的时候分配内存&#xff0c;并且是分配在…

extends和implements区别

extends和implements区别 extends与implements的不同 1、在类的声明中&#xff0c;通过关键字extends来创建一个类的子类。 一个类通过关键字implements声明自己使用一个或者多个接口。 extends 是继承某个类, 继承之后可以使用父类的方法, 也可以重写父类的方法; imple…

评论:电商巨头们谁有勇气晒晒“价格战”账单?

摘要&#xff1a;国内电商接二连三上演的“价格战”&#xff0c;点燃了消费者的购买热情。在笔者看来&#xff0c;如果有哪个大型电商有勇气亮出价格战账单&#xff0c;那对竞争对手的刺激和打击效果将非同一般。晒出了账单后&#xff0c;消费者对购物场所的选择也将一目了然&a…

The xxx collides with a package/type

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 当类和包&#xff0c;重名时&#xff0c;包会报错误&#xff1a;The package aaa.a collides with a type&#xff1b;类也会报警告&…

Hive 行列转换

在京东众多业务中&#xff0c;促销业务充满了复杂性和挑战性&#xff0c;因为业务的灵活性&#xff0c;很多数据都存储成xml和json格式数据&#xff0c;这就要求下游数据分析师们需要对其做解析后方可使用 。 在众多操作中 &#xff0c;有一种是需要对数据做行列转换操作。 数据…

[译] 论 Rust 和 WebAssembly 对源码地址索引的极限优化

原文地址&#xff1a;Oxidizing Source Maps with Rust and WebAssembly原文作者&#xff1a;Nick Fitzgerald译文出自&#xff1a;掘金翻译计划本文永久链接&#xff1a;github.com/xitu/gold-m…译者&#xff1a;D-kylinTom Tromey 和我尝试使用 Rust 语言进行编码&#xff0…

Java WebService 简单实例

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 前言&#xff1a;朋友们开始以下教程前&#xff0c;请先看第五大点的注意事项&#xff0c;以避免不必要的重复操作。 一、准备工作&…