Description

题库链接

给定一个 \(N\) 个点 \(M\) 条边的有向无环图,每条边长度都是 \(1\)。请找到一个点,使得删掉这个点后剩余的图中的最长路径最短。

\(1\leq N\leq 500 000,1\leq M\leq 1 000 000\)

Solution

比较神...

值得注意的是,对于一张 \(\text{DAG}\) 的拓扑序,任意从中截断那么前一部分以及后一部分的点都是连续的。

考虑按拓扑序来做,我们需要维护的就只是左边一部分内的最长路,以及右边一部分内的最长路。

除此之外还要维护经过被“割开”边的最长路。

对于删除一个点,我们需要做的就是将“割边”转移,维护上述需要维护的信息。

可以用可删除的堆来实现,不过考虑到空间的花销,用权值线段树可以实现同样的功能。

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 500000+5, inf = ~0u>>1; int n, m, u, v, c1[N], c2[N], q[N];
struct graph {
struct tt {int to, next; }edge[N<<1];
int path[N], top, in[N];
void add(int u, int v) {edge[++top] = (tt){v, path[u]}, path[u] = top, ++in[v]; }
void topsort(int* c, int flag) {
queue<int>Q; int cnt = 0;
for (int i = 1; i <= n; i++) if (!in[i]) Q.push(i);
while (!Q.empty()) {
int u = Q.front(); Q.pop(); if (flag) q[++cnt] = u;
for (int i = path[u]; i; i = edge[i].next) {
--in[edge[i].to]; c[edge[i].to] = max(c[edge[i].to], c[u]+1);
if (in[edge[i].to] == 0) Q.push(edge[i].to);
}
}
}
}g1, g2;
struct Segment_tree {
#define lr(o) (o<<1)
#define rr(o) (o<<1|1)
int mx[N<<2], cnt[N<<2];
Segment_tree() {memset(mx, -1, sizeof(mx)); }
void modify(int o, int l, int r, int loc, int key) {
if (l == r) {
cnt[o] += key;
if (cnt[o] == 1) mx[o] = l;
else if (cnt[o] == 0) mx[o] = -1;
return;
}
int mid = (l+r)>>1;
if (loc <= mid) modify(lr(o), l, mid, loc, key);
else modify(rr(o), mid+1, r, loc, key);
mx[o] = max(mx[lr(o)], mx[rr(o)]);
}
}T; void work() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) {
scanf("%d%d", &u, &v); g1.add(u, v), g2.add(v, u);
}
g1.topsort(c1, 1), g2.topsort(c2, 0);
int ans = inf, pos;
for (int i = 1; i <= n; i++) T.modify(1, 0, n, c2[i], 1);
for (int id = 1; id <= n; id++) {
int u = q[id];
for (int i = g2.path[u]; i; i = g2.edge[i].next)
T.modify(1, 0, n, c2[u]+c1[g2.edge[i].to]+1, -1);
T.modify(1, 0, n, c2[u], -1);
if (T.mx[1] < ans) ans = T.mx[1], pos = u;
for (int i = g1.path[u]; i; i = g1.edge[i].next)
T.modify(1, 0, n, c1[u]+c2[g1.edge[i].to]+1, 1);
T.modify(1, 0, n, c1[u], 1);
}
printf("%d %d\n", pos, ans);
}
int main() {work(); return 0; }

[POI 2014]RAJ-Rally的更多相关文章

  1. bzoj 3522 / 4543 [POI 2014] Hotel - 动态规划 - 长链剖分

    题目传送门 bzoj 3522 需要root权限的传送点 bzoj 4543 快速的传送点 慢速的传送点 题目大意 给定一棵树,问有多少个无序三元组$(x, y, z)$使得这三个不同点在树上两两距离 ...

  2. 解题:POI 2014 Ant colony

    题面 既然我们只知道最后数量为$k$的蚂蚁会在特殊边上被吃掉,不妨逆着推回去,然后到达每个叶节点的时候就会有一个被吃掉的蚂蚁的区间,然后二分一下就好啦 #include<cstdio> # ...

  3. POI 2014 HOTELS (树形DP)

    题目链接 HOTELS 依次枚举每个点,以该点为中心扩展. 每次枚举的时候,从该点的儿子依次出发,搜完一个儿子所有的点之后进行答案统计. 这里用了一个小trick. #include <bits ...

  4. [POI 2014] Couriers

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3524 [算法] 首先离线 , 将询问按右端点排序 如果我们知道[l , r]这个区间 ...

  5. [POI 2014] Little Bird

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3831 [算法] 单调队列优化动态规划 时间复杂度 : O(N) [代码] #incl ...

  6. bzoj 3872 [ Poi 2014 ] Ant colony —— 二分

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3872 从食蚁兽所在的边向叶节点推,会得到一个渐渐放大的取值区间,在叶子节点上二分有几群蚂蚁符 ...

  7. [POI 2014]PTA-Little Bird

    Description 题库连接 给你 \(n\) 棵树,第 \(i\) 棵树的高度为 \(d_i\).有一只鸟从 1 号树出发,每次飞跃不能超过 \(k\) 的距离.若飞到下一棵树的高度大于等于这一 ...

  8. Solution -「POI 2014」「洛谷 P5904」HOT-Hotels 加强版

    \(\mathcal{Description}\)   Link.   给定一棵 \(n\) 个点的树,求无序三元组 \((u,v,w)\) 的个数,满足其中任意两点树上距离相等.   \(n\le1 ...

  9. POI题解整合

    我也不知道为啥我就想把POI的题全都放到一篇blog里写完. POI 2005 SAM-Toy Cars 贪心,每次选下次出现最晚的. POI 2006 KRA-The Disks 箱子位置单调,所以 ...

随机推荐

  1. [ACM_数据结构] Color the ball [线段树水题][数组开大]

    Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次 ...

  2. 关于Git bash 在win10重装系统情况下闪退并生成mintty.exe.stackdump文件的问题

    问题内容:在重装win10系统情况下,有可能会出现安装Git后右击Git bash会出现闪退并生成mintty.exe.stackdump文件 个人解决方案:查看网络上各位网友的意见和解决方法后,自己 ...

  3. C# 二维码/条形码入门操作

    效果图: 先给之前的群友道个歉,说声不好意思.QRCoder 只支持二维码,没有条形码. 以上demo生成条形码是用 BarcodeLib 这个库,识别是用 zxing,二维码生成用 QRCoder, ...

  4. web请求的状态码

    摘录于  https://www.cnblogs.com/lovychen/p/6256343.html 1xx消息 这一类型的状态码,代表请求已被接受,需要继续处理.这类响应是临时响应,只包含状态行 ...

  5. Day 42 协程. IO 并发

    一.什么是协程? 是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 协程相比于线程切换效率更快了. ...

  6. fastAdmin根据状态显示是否显示操作按钮

    根据状态决定是否显示某个操作按钮 代码如下:

  7. 栈的实现——java

    和C++一样,JDK包中也提供了"栈"的实现,它就是集合框架中的Stack类.关于Stack类的原理,在"Java 集合系列07之 Stack详细介绍(源码解析)和使用示 ...

  8. Django(图书管理系统1)

    day63 内容回顾     1. 单表的增删改查         1. 删和改             1. GET请求 URL传值                 1. 格式            ...

  9. MFC多线程技术

    MFC中有两类线程,分别称之为工作者线程和用户界面线程.二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环. 工作者线程没笑消息机制,通常用来执行后台计算和维护任务,如 ...

  10. 页面按钮埋点+跟踪location.search

    <a href="javascript: void(0)" onclick="setUrl('https://baoxian.pingan.com/pa18shop ...