3832: [Poi2014]Rally
3832: [Poi2014]Rally
分析:
首先可以考虑删除掉一个点后,计算最长路。
设$f[i]$表示从起点到i的最长路,$g[i]$表示从i出发到终点的最长路。那么经过一条边的最长路就是$f[u]+1+g[v]$。
删除一个点x后,会使一些路径没了。考虑这些路径的特点。我们它比x拓扑序小的设为集合S,拓扑序大的设为T。
1、如果以前的一条路径经过x,那么去掉x后,考虑如何去掉这些路径的影响。只需将x的入边删掉就行了。
2、那么如何统计新的答案,并且新的路径不能经过x。此处是一个有意思的地方,统计所有起点在S,终点在T的所有边,会发现所有经过这些边的路径都不会经过x。(这些路径中一般是起代替x的作用的,但是存在一些边并没有代替x,但是对答案不影响)。
那么做法就出来了:按照拓扑序删点,不断维护起点在S,终点在T的边,每条边权值为$f[u]+1+g[v]$,取最大值。
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ;
int g[N], f[N], T[N << ], cnt[N << ], q[N], n; struct Edge{
int to[N << ], nxt[N << ], head[N], En, deg[N << ];
inline void add_edge(int u,int v) {
++En; to[En] = v, nxt[En] = head[u]; head[u] = En; deg[v] ++;
}
}Z, F; void solve() {
int L = , R = ;
for (int i = ; i <= n; ++i) if (F.deg[i] == ) q[++R] = i;
while (L <= R) {
int u = q[L ++];
for (int i = F.head[u]; i; i = F.nxt[i]) {
int v = F.to[i];
g[v] = max(g[v], g[u] + );
if (!(--F.deg[v])) q[++R] = v;
}
}
L = , R = ;
for (int i = ; i <= n; ++i) if (Z.deg[i] == ) q[++R] = i;
while (L <= R) {
int u = q[L ++];
for (int i = Z.head[u]; i; i = Z.nxt[i]) {
int v = Z.to[i];
f[v] = max(f[v], f[u] + );
if (!(--Z.deg[v])) q[++R] = v;
}
}
}
void update(int l,int r,int rt,int p,int v) {
if (l == r) {
cnt[rt] += v;
if (cnt[rt] > ) T[rt] = l;
else T[rt] = -, cnt[rt] = ;
return ;
}
int mid = (l + r) >> ;
if (p <= mid) update(l, mid, rt << , p, v);
else update(mid + , r, rt << | , p, v);
T[rt] = max(T[rt << ], T[rt << | ]);
}
int main() {
n = read();int m = read();
for (int i = ; i <= m; ++i) {
int x = read(), y = read();
Z.add_edge(x, y);
F.add_edge(y, x);
}
solve();
int ans = 1e9, pt;
for (int i = ; i <= n; ++i) update(, n, , g[i], );
for (int i = ; i <= n; ++i) {
int x = q[i];
for (int j = F.head[x]; j; j = F.nxt[j])
update(, n, , g[x] + f[F.to[j]] + , -);
update(, n, , g[x], -);
if (T[] < ans) ans = T[], pt = x;
for (int j = Z.head[x]; j; j = Z.nxt[j])
update(, n, , f[x] + g[Z.to[j]] + , );
update(, n, , f[x], );
}
cout << pt << " " << ans;
return ;
}
3832: [Poi2014]Rally的更多相关文章
- BZOJ 3832: [Poi2014]Rally
Sol 线段树+拓扑序. 先把图的拓扑序搞出来,然后统计从起点到该点最长链,从该点到终点的最长链,然后建个起点终点,这里跟网络流很像,把它统一到一个有起点的图中,这里也要注意下细节处理.S,T的一个边 ...
- 【BZOJ】3832: [Poi2014]Rally
题意 \(n(2 \le n \le 500000)\)个点\(m(1 \le m \le 1000000)\)条边的有向无环图,找到一个点,使得删掉这个点后剩余图中的最长路径最短. 分析 神题不会做 ...
- BZOJ:3832: [Poi2014]Rally
题意: 给出$DAG$,询问删掉哪个点之后最长路径最短 思路: 我们令$f[x]$表示从最远的点到达它的距离,$g[x]$表示它能够到达最远的点的距离 那么对于$(x -> y)$一条边来说,它 ...
- 【BZOJ3832】[POI2014]Rally(拓扑排序,动态规划)
[BZOJ3832][POI2014]Rally(拓扑排序,动态规划) 题面 BZOJ,权限题 洛谷 题解 这题好强啊,感觉学了好多东西似的. 首先发现了一个图画的很好的博客,戳这里 然后我来补充一下 ...
- BZOJ3832[Poi2014]Rally——权值线段树+拓扑排序
题目描述 An annual bicycle rally will soon begin in Byteburg. The bikers of Byteburg are natural long di ...
- BZOJ3832 : [Poi2014]Rally
f[0][i]为i出发的最长路,f[1][i]为到i的最长路 新建源汇S,T,S向每个点连边,每个点向T连边 将所有点划分为两个集合S与T,一开始S中只有S,其它点都在T中 用一棵线段树维护所有连接属 ...
- [POI2014]Rally
OJ题号:BZOJ3832.洛谷3573 思路: 建立超级源汇$S$和$T$,DP求出分别以$S$和$T$为源点的最长路$diss$和$dist$. 对于每条边$i$,设定一个权值$w_i=diss_ ...
- BZOJ3832: [Poi2014]Rally(拓扑排序 堆)
题意 题目链接 Sol 最直观的思路是求出删除每个点后的最长路,我们考虑这玩意儿怎么求 设\(f[i]\)表示以\(i\)结尾的最长路长度,\(g[i]\)表示以\(i\)开始的最长路长度 根据DAG ...
- BZOJ3832 [Poi2014]Rally 【拓扑序 + 堆】
题目链接 BZOJ3832 题解 神思路orz,根本不会做 设\(f[i]\)为到\(i\)的最长路,\(g[i]\)为\(i\)出发的最长路,二者可以拓扑序后\(dp\)求得 那么一条边\((u,v ...
随机推荐
- MySQL Group Replication配置
MySQL Group Replication简述 MySQL 组复制实现了基于复制协议的多主更新(单主模式). 复制组由多个 server成员构成,并且组中的每个 server 成员可以独立地执行事 ...
- sql面试
1.用一条SQL语句 查询出每门课都大于80分的学生姓名 name kecheng fenshu 张三 语文 81张三 数学 75李四 语文 ...
- 通过nginx 访问 centos 7 服务器上的.Net Core
先安装依赖 # yum -y install pcre-devel openssl openssl-devel # yum -y install gcc gcc-c++ autoconf automa ...
- python面试十题
问题1: 请问如何修改以下python代码,使得下面的代码调用类A的show方法? class A(): def show(self): print("base show") cl ...
- layer的alert图
layer.alert("xxx",1); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 及以后
- C++ 课堂作业1.0
c++第一次课堂作业点这里 题目要求:输入半径,计算圆的面积,在调用外部函数,无需使用类.
- Eclipse插件安装方法大全
1. M2e maven2插件安装 参考地址:http://www.sonatype.com/books/m2eclipse-book/reference/install-sect-marketpla ...
- python里的splitlines具体解释
Python的split方法函数能够切割字符串成列表,默认是以空格作为分隔符sep来切割字符串. In [1]: s = "www jeapedu com" In [2]: ...
- 1054. [HAOI2008]移动玩具【BFS】
Description 在一个4*4的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动 时只能将玩具向上下左右四个方向移动,并且移动的位置不能有玩具,请你用最少的移 ...
- 'vue-cli-service' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
首先把 node_modules 文件夹删除 然后运行以下命令: cnpm install 这样就可以正常运行