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的更多相关文章

  1. BZOJ 3832: [Poi2014]Rally

    Sol 线段树+拓扑序. 先把图的拓扑序搞出来,然后统计从起点到该点最长链,从该点到终点的最长链,然后建个起点终点,这里跟网络流很像,把它统一到一个有起点的图中,这里也要注意下细节处理.S,T的一个边 ...

  2. 【BZOJ】3832: [Poi2014]Rally

    题意 \(n(2 \le n \le 500000)\)个点\(m(1 \le m \le 1000000)\)条边的有向无环图,找到一个点,使得删掉这个点后剩余图中的最长路径最短. 分析 神题不会做 ...

  3. BZOJ:3832: [Poi2014]Rally

    题意: 给出$DAG$,询问删掉哪个点之后最长路径最短 思路: 我们令$f[x]$表示从最远的点到达它的距离,$g[x]$表示它能够到达最远的点的距离 那么对于$(x -> y)$一条边来说,它 ...

  4. 【BZOJ3832】[POI2014]Rally(拓扑排序,动态规划)

    [BZOJ3832][POI2014]Rally(拓扑排序,动态规划) 题面 BZOJ,权限题 洛谷 题解 这题好强啊,感觉学了好多东西似的. 首先发现了一个图画的很好的博客,戳这里 然后我来补充一下 ...

  5. BZOJ3832[Poi2014]Rally——权值线段树+拓扑排序

    题目描述 An annual bicycle rally will soon begin in Byteburg. The bikers of Byteburg are natural long di ...

  6. BZOJ3832 : [Poi2014]Rally

    f[0][i]为i出发的最长路,f[1][i]为到i的最长路 新建源汇S,T,S向每个点连边,每个点向T连边 将所有点划分为两个集合S与T,一开始S中只有S,其它点都在T中 用一棵线段树维护所有连接属 ...

  7. [POI2014]Rally

    OJ题号:BZOJ3832.洛谷3573 思路: 建立超级源汇$S$和$T$,DP求出分别以$S$和$T$为源点的最长路$diss$和$dist$. 对于每条边$i$,设定一个权值$w_i=diss_ ...

  8. BZOJ3832: [Poi2014]Rally(拓扑排序 堆)

    题意 题目链接 Sol 最直观的思路是求出删除每个点后的最长路,我们考虑这玩意儿怎么求 设\(f[i]\)表示以\(i\)结尾的最长路长度,\(g[i]\)表示以\(i\)开始的最长路长度 根据DAG ...

  9. BZOJ3832 [Poi2014]Rally 【拓扑序 + 堆】

    题目链接 BZOJ3832 题解 神思路orz,根本不会做 设\(f[i]\)为到\(i\)的最长路,\(g[i]\)为\(i\)出发的最长路,二者可以拓扑序后\(dp\)求得 那么一条边\((u,v ...

随机推荐

  1. Error:Could not find com.android.tools.build:gradle:3.0.0

    Error:Could not find com.android.tools.build:gradle:3.0.Searched in the following locations:    file ...

  2. 手把手教你制作AppPreview视频并上传到appStore进行审核

    手把手教你制作AppPreview视频并上传到appStore进行审核 注意,你需要使用iMovie才能够制作AppPreview视频文件,用QuickTime录制的无效! 最终效果 1. 新建一个事 ...

  3. Linux 系统开机自启的配置文件

    程序开机启动的配置文件(/etc/rc.local) # 系统级别 ntsysv # 图形界面设置自启程序 chkconfig(/etc/init.d/sshd) 处理开机启动的文件 # 用户级别 # ...

  4. Entity Framework的基本操作

    一.使用基本的方法进行增删改查             二.使用状态进行增删改查,即使用基类对象进行操作                         三.多个表同时进行添加 添加数据后获取自动增长 ...

  5. lumen框架的辅助函数

    简介 Laravel 包含一些多样化的 PHP 辅助函数函数.许多在 Laravel 自身框架中使用:如果你觉得实用,也可以在你应用当中使用. 可用方法 数组 array_add array_coll ...

  6. Hadoop HBase概念学习系列之模式设计(十)

      Hbase与RDBMS的区别在于:HBase的Cell(每条数据记录中的数据项)是具有版本描述的(versioned),行是有序的,列(qualifier)在所属列簇(Column familie ...

  7. 企业生产环境集群稳定性-HA就行吗?

    在企业生产中,集群一旦运行,是要尽可能的将损失降到最低,现在所有的大数据技术都有HA,spark的.Hadoop的.HBase的等等, HA分冷备和热备,热备是集群自带的,冷备就是硬件的. 这样一种情 ...

  8. Sql Server 流程控制语句

    T-SQL中用来编写流程控制模块的语句有:BEGIN...AND语句.IF...ELSE语句.CASE语句.WHILE语句.GOTO语句.BREAK语句.WAITFOR语句和RETURN语句. 批处理 ...

  9. BZOJ2435:[NOI2011]道路修建 (差分)

    Description 在 W 星球上有 n 个国家.为了各自国家的经济发展,他们决定在各个国家 之间建设双向道路使得国家之间连通.但是每个国家的国王都很吝啬,他们只愿 意修建恰好 n – 1条双向道 ...

  10. error:Assertion failed ((unsigned)i0 < (unsigned)size.p[0]) in cv::Mat::at

    问题原因: 访问像素时指针越界造成的 解决办法: 1.检查指针下标是否正确 2.row和col是否写反了