BZOJ:3832: [Poi2014]Rally
题意:
给出$DAG$,询问删掉哪个点之后最长路径最短
思路:
我们令$f[x]$表示从最远的点到达它的距离,$g[x]$表示它能够到达最远的点的距离
那么对于$(x -> y)$一条边来说,它所在的最长路径就是 $f[x] + 1 + g[y]$
我们按照拓扑序依次删点
我们发现此时删去一个点,那么可能存在的最长的路径是
和它同一层的点所在的路径,以及它前一层的点所在的路径,以及它后一层的点所在的路径
因为它只会影响到它前一层的点和后一层的点
那么我们删去它所有入边的贡献,以及它本身的$g[x]$的贡献
再更新答案后
我们加入它出边的贡献,以及它本身的$f[x]$的贡献
#include <bits/stdc++.h>
using namespace std; #define N 500010
int n, m;
vector <int> G[][N];
int f[N], g[N]; namespace SEG
{
int cnt[N << ], Max[N << ];
void build(int id, int l, int r)
{
cnt[id] = Max[id] = ;
if (l == r)
return;
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
}
void update(int id, int l, int r, int pos, int v)
{
if (pos == ) return;
if (l == r)
{
cnt[id] += v;
if (cnt[id] > ) Max[id] = pos;
else Max[id] = ;
return;
}
int mid = (l + r) >> ;
if (pos <= mid) update(id << , l, mid, pos, v);
else update(id << | , mid + , r, pos, v);
Max[id] = max(Max[id << ], Max[id << | ]);
}
} int id[N], d[][N];
void Toposort()
{
id[] = ;
memset(f, , sizeof f);
memset(g, , sizeof g);
queue <int> q;
for (int i = ; i <= n; ++i)
if (d[][i] == )
q.push(i);
while (!q.empty())
{
int u = q.front(); q.pop();
id[++id[]] = u;
for (int v, it = , len = G[][u].size(); it < len; ++it)
{
v = G[][u][it];
if (--d[][v] == )
{
f[v] = f[u] + ;
q.push(v);
}
}
}
for (int i = ; i <= n; ++i)
if (d[][i] == )
q.push(i);
while (!q.empty())
{
int u = q.front(); q.pop();
for (int v, it = , len = G[][u].size(); it < len; ++it)
{
v = G[][u][it];
if (--d[][v] == )
{
g[v] = g[u] + ;
q.push(v);
}
}
}
} void Run()
{
while (scanf("%d%d", &n, &m) != EOF)
{
for (int i = ; i <= n; ++i)
G[][i].clear(), G[][i].clear();
memset(d, , sizeof d);
SEG::build(, , m);
for (int i = , u, v; i <= m; ++i)
{
scanf("%d%d", &u, &v);
G[][u].push_back(v); ++d[][v];
G[][v].push_back(u); ++d[][u];
}
Toposort();
for (int i = ; i <= n; ++i)
SEG::update(, , m, g[i], );
int Min = (int)1e9, pos = -;
for (int x, i = ; i <= n; ++i)
{
x = id[i];
for (int v, it = , len = G[][x].size(); it < len; ++it)
{
v = G[][x][it];
SEG::update(, , m, f[v] + + g[x], -);
}
SEG::update(, , m, g[x], -);
int now = SEG::Max[];
if (now < Min)
{
Min = now;
pos = x;
}
SEG::update(, , m, f[x], );
for (int v, it = , len = G[][x].size(); it < len; ++it)
{
v = G[][x][it];
SEG::update(, , m, f[x] + + g[v], );
}
}
printf("%d %d\n", pos, Min);
}
} int main()
{
#ifdef LOCAL
freopen("Test.in", "r", stdin);
#endif Run();
return ;
}
BZOJ:3832: [Poi2014]Rally的更多相关文章
- 【BZOJ】3832: [Poi2014]Rally
题意 \(n(2 \le n \le 500000)\)个点\(m(1 \le m \le 1000000)\)条边的有向无环图,找到一个点,使得删掉这个点后剩余图中的最长路径最短. 分析 神题不会做 ...
- 3832: [Poi2014]Rally
3832: [Poi2014]Rally 链接 分析: 首先可以考虑删除掉一个点后,计算最长路. 设$f[i]$表示从起点到i的最长路,$g[i]$表示从i出发到终点的最长路.那么经过一条边的最长路就 ...
- BZOJ 3832: [Poi2014]Rally
Sol 线段树+拓扑序. 先把图的拓扑序搞出来,然后统计从起点到该点最长链,从该点到终点的最长链,然后建个起点终点,这里跟网络流很像,把它统一到一个有起点的图中,这里也要注意下细节处理.S,T的一个边 ...
- 【BZOJ3832】[POI2014]Rally(拓扑排序,动态规划)
[BZOJ3832][POI2014]Rally(拓扑排序,动态规划) 题面 BZOJ,权限题 洛谷 题解 这题好强啊,感觉学了好多东西似的. 首先发现了一个图画的很好的博客,戳这里 然后我来补充一下 ...
- BZOJ:3441 乌鸦喝水
bzoj:3441 乌鸦喝水 题目传送门 Description 一只乌鸦在自娱自乐,它在面前放了n个有魔力的水缸,水缸里装有无限的水. 他准备从第1个水缸飞到第n个水缸,共m次.在飞过一个水缸的过程 ...
- 【BZOJ】3835: [Poi2014]Supercomputer
题意 \(n(1 \le 1000000)\)个点的有根树,\(1\)号点为根,\(q(1 \le 1000000)\)次询问,每次给一个\(k\),每一次可以选择\(k\)个未访问的点,且父亲是访问 ...
- 【BZOJ】3834: [Poi2014]Solar Panels
http://www.lydsy.com/JudgeOnline/problem.php?id=3834 题意:求$max\{(i,j)\}, smin<=i<=smax, wmin< ...
- BZOJ3832[Poi2014]Rally——权值线段树+拓扑排序
题目描述 An annual bicycle rally will soon begin in Byteburg. The bikers of Byteburg are natural long di ...
- [POI2014]Rally
OJ题号:BZOJ3832.洛谷3573 思路: 建立超级源汇$S$和$T$,DP求出分别以$S$和$T$为源点的最长路$diss$和$dist$. 对于每条边$i$,设定一个权值$w_i=diss_ ...
随机推荐
- NodeJS-004-Oracle驱动编译
一.参考文章 https://community.oracle.com/docs/DOC-931127 http://www.cnblogs.com/stone_w/p/4794747.html ht ...
- 制作Windows U盘镜像
目的:制作windows server 2008 U盘镜像 需要的共具: 1.一个格式为FAT并且至少4G的U盘, 2.UltraISO软件, 3.一个windows server 2008 ISO文 ...
- Android编译系统(Android.mk文件详解)
[Android-NDK(Native Development Kit) docs文档] NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成a ...
- PopupMenu弹出菜单
CMenu MoviePopupMenu;//声明 MoviePopupMenu.CreatePopupMenu();//创建弹出菜单 根据对象类型增加弹出项 ) // FLASH对象 { CStri ...
- c#图片生成png格式和原图不同
下面这种,会生成和原图类似的图片,png格式的图片该是空的地方仍旧是空的
- 图的建立(邻接矩阵)+深度优先遍历+广度优先遍历+Prim算法构造最小生成树(Java语言描述)
主要参考资料:数据结构(C语言版)严蔚敏 ,http://blog.chinaunix.net/uid-25324849-id-2182922.html 代码测试通过. package 图的建 ...
- linux常用的一些访问目录
救命三键(Ctrl+Alt+Delete) /var/log 如果是网络服务的问题时,请到 这个目录里头去查阅一下 log file (登录档): /etc/rc.local 修改挂载 ...
- java类的成员初始化顺序和初始化块知识
java类的成员初始化顺序和初始化块知识 转自:http://blog.csdn.net/lgfeng218/article/details/7606735 属性.方法.构造方法和自由块都是类中的成员 ...
- java启动3个线程轮流打印数字
转自:http://blog.csdn.net/u014011112/article/details/50988769 http://blog.csdn.net/perrywork/article/d ...
- linux中增加swap分区文件的步骤方法
一.swap交换分区 Swap分区在系统的物理内存不够用的时候,把硬盘空间中的一部分空间释放出来,以供当前运行的程序使用.那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临 ...