题目链接

BZOJ3832

题解

神思路orz,根本不会做

设\(f[i]\)为到\(i\)的最长路,\(g[i]\)为\(i\)出发的最长路,二者可以拓扑序后\(dp\)求得

那么一条边\((u,v)\)的对应的最长链就是\(f[u] + 1 + g[v]\)

我们人为加入源汇点\(S\),\(T\),\(S\)向每个点连边,每个点向\(T\)连边

我们考虑把整个图划分开

一开始所有点都在\(T\)这边,割边为所有\(S\)的边

然后我们按照拓扑序把点逐一加入\(S\)集合中

加入时,我们删去\(S\)集合连向该点的边,然后询问所有边的最大值,即为删去该点的最长链

加入后,我们加入该点连向\(T\)集合的边

由于是按照拓扑序,所以以上提到的所有边就是该点的所有入边/出边

然后所有边的最大值可以用堆或者线段树维护

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u]; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 500005,maxm = 2000005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
struct Heap{
priority_queue<int> a,b;
void ck(){while (!b.empty() && a.top() == b.top()) a.pop(),b.pop();}
int size(){return a.size() - b.size();}
void ins(int x){ck(); a.push(x);}
void del(int x){ck(); b.push(x);}
int top(){ck(); return size() ? a.top() : 0;}
}H;
int n,m,f[maxn],g[maxn],s[maxn];
int q[maxn],head,tail;
int h[maxn],de[maxn],ne;
int hi[maxn],nei;
struct EDGE{int to,nxt;}ed[maxm],e[maxm];
inline void build(int u,int v){
ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
de[v]++;
e[++nei] = (EDGE){u,hi[v]}; hi[v] = nei;
}
void topu(){
head = 0; tail = -1; int u;
REP(i,n) if (!de[i]) q[++tail] = i;
REP(i,n){
s[i] = u = q[head++];
Redge(u) if (!(--de[ed[k].to])) q[++tail] = ed[k].to;
}
}
void init(){
REP(i,n){
int u = s[i];
Redge(u) f[ed[k].to] = max(f[ed[k].to],f[u] + 1);
}
for (int i = n; i; i--){
int u = s[i];
Redge(u) g[u] = max(g[u],g[ed[k].to] + 1);
}
}
void solve(){
int ans = INF,ansu = 0,x;
REP(i,n) H.ins(g[i]);
REP(i,n){
int u = s[i];
H.del(g[u]);
for (int k = hi[u]; k; k = e[k].nxt)
H.del(f[e[k].to] + 1 + g[u]);
x = H.top();
if (x < ans) ans = x,ansu = u;
H.ins(f[u]);
Redge(u) H.ins(f[u] + 1 + g[ed[k].to]);
}
printf("%d %d\n",ansu,ans);
}
int main(){
n = read(); m = read();
int a,b;
REP(i,m){
a = read(); b = read();
build(a,b);
}
topu();
init();
//REP(i,n) printf("node%d f = %d g = %d\n",i,f[i],g[i]);
solve();
return 0;
}

BZOJ3832 [Poi2014]Rally 【拓扑序 + 堆】的更多相关文章

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

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

  2. 【BZOJ-3832】Rally 拓扑序 + 线段树 (神思路题!)

    3832: [Poi2014]Rally Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 168  Solved:  ...

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

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

  4. 并不对劲的bzoj3832: [Poi2014]Rally

    传送门-> 这题的原理看上去很神奇. 称拓扑图中入度为0的点为“起点”,出度为0的点为“终点”. 因为“起点”和“终点”可能有很多个,算起来会很麻烦,所以新建“超级起点”S,向所有点连边,“超级 ...

  5. BZOJ3832 : [Poi2014]Rally

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

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

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

  7. BZOJ-4010 菜肴制作 贪心+堆+(拓扑图拓扑序)

    无意做到...char哥还中途强势插入干我...然后据他所言,看了一会题,一转头,我爆了正解....可怕 4010: [HNOI2015]菜肴制作 Time Limit: 5 Sec Memory L ...

  8. [POI2014]Rally

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

  9. 3832: [Poi2014]Rally

    3832: [Poi2014]Rally 链接 分析: 首先可以考虑删除掉一个点后,计算最长路. 设$f[i]$表示从起点到i的最长路,$g[i]$表示从i出发到终点的最长路.那么经过一条边的最长路就 ...

随机推荐

  1. Siki_Unity_0_Unity A计划直播视频

    Unity A计划直播视频 2017-07-04直播 任务1:如何识别以招聘来招培训生的公司: 打着招聘的旗号帮培训机构找培训生 关键词:实训生 任务2:如何识别一个公司的好坏和规模大小: 猎聘(中高 ...

  2. lintcode174 删除链表中倒数第n个节点

    删除链表中倒数第n个节点   给定一个链表,删除链表中倒数第n个节点,返回链表的头节点. 注意事项 链表中的节点个数大于等于n 您在真实的面试中是否遇到过这个题? Yes 样例 给出链表1->2 ...

  3. Apache POI:Excel读写库

    1)Apache POI 简介 Apache POI是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office格式档案读和写 ...

  4. 正式放弃Edge,重新拥抱Chrome

    从Edge还叫斯巴达的时候我就开始用了,本来对浏览器的要求也没多高,能够打开多个选项卡,稳定,支持最新的规范就好了. 但是Edge真的是越来越让我失望了,卡死问题越来越多,崩溃越来越频繁,我也快奔溃了 ...

  5. EF中如何为表添加新的字段和映射

    首先先了解一下ef生成的模型edmx的代码,传送门:http://www.cnblogs.com/yushengbo/p/4807715.html 一.添加新的字段 例子就用我现在项目的这个吧,首先在 ...

  6. PAT-甲级解题目录

    PAT甲级题目:点这里 pat解题列表 题号 标题 题目类型  10001 1001 A+B Format (20 分)  字符串处理  1003 1003 Emergency (25 分) 最短路径 ...

  7. Java进阶——— 线程池的原理分析

    前言 在了解线程池之前,其实首先出现的疑问是:为什么要使用线程池,其次是了解什么是线程池,最后是如何使用线程池,带着疑问去学习. 为什么要使用 前面多线程文章中,需要使用线程就开启一个新线程,简单方便 ...

  8. Halcon图像采集助手提示找不到指定DLL文件

    问题原因: Halcon软件更新导致某些图像采集DLL失效,这个时候就需要去MVTEC官网下载图像采集接口补丁程序,MVTEC官网地址http://www.mvtec.com/. 对于其他模块失效的D ...

  9. 《剑指Offer》题三十一~题四十

    三十一.栈的压入.弹出序列 题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的数字均不相等.例如,序列{1, 2, 3, 4 ,5}是某栈的压栈序列 ...

  10. 《安装ubuntu及VMware以及相关问题汇总》

    一.VMware Ubuntu安装详细过程 http://blog.csdn.net/u013142781/article/details/50529030 二.VMware Tools (ubunt ...