3832: [Poi2014]Rally

Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special Judge
Submit: 168  Solved: 84
[Submit][Status][Discuss]

Description

An annual bicycle rally will soon begin in Byteburg. The bikers of Byteburg are natural long distance cyclists. Local representatives of motorcyclists, long feuding the cyclists, have decided to sabotage the event.
There are   intersections in Byteburg, connected with one way streets. Strangely enough, there are no cycles in the street network - if one can ride from intersection U to intersection V , then it is definitely impossible to get from V to U.
The rally's route will lead through Byteburg's streets. The motorcyclists plan to ride their blazing machines in the early morning of the rally day to one intersection and completely block it. The cyclists' association will then of course determine an alternative route but it could happen that this new route will be relatively short, and the cyclists will thus be unable to exhibit their remarkable endurance. Clearly, this is the motorcyclists' plan - they intend to block such an intersection that the longest route that does not pass through it is as short as possible.
给定一个N个点M条边的有向无环图,每条边长度都是1。
请找到一个点,使得删掉这个点后剩余的图中的最长路径最短。

Input

In the first line of the standard input, there are two integers, N and M(2<=N<=500 000,1<=M<=1 000 000), separated by a single space, that specify the number of intersections and streets in Byteburg. The intersections are numbered from   to  . The   lines that follow describe the street network: in the  -th of these lines, there are two integers, Ai, Bi(1<=Ai,Bi<=N,Ai<>Bi), separated by a single space, that signify that there is a one way street from the intersection no. Ai to the one no. Bi.
第一行包含两个正整数N,M(2<=N<=500 000,1<=M<=1 000 000),表示点数、边数。
接下来M行每行包含两个正整数A[i],B[i](1<=A[i],B[i]<=N,A[i]<>B[i]),表示A[i]到B[i]有一条边。

Output

The first and only line of the standard output should contain two integers separated by a single space. The first of these should be the number of the intersection that the motorcyclists should block, and the second - the maximum number of streets that the cyclists can then ride along in their rally. If there are many solutions, your program can choose one of them arbitrarily.
包含一行两个整数x,y,用一个空格隔开,x为要删去的点,y为删除x后图中的最长路径的长度,如果有多组解请输出任意一组。

Sample Input

6 5
1 3
1 4
3 6
3 4
4 5

Sample Output

1 2

HINT

Source

鸣谢Claris提供SPJ及译文

Solution

神思路!

直接求最长路径的方法是拓扑排序后DP

那么这道题先建立源汇,那么最长路径就是S-->T的最长路

实际上对于一条边<u,v>经过这条边的最长路就是S-->u的最长+<u,v>+v-->T的最长

所以定义f[x][0]和f[x][1]表示S到x的最长,x到T的最长,那么我们对一条边<u,v>他的权值定义为f[x][0]+f[v][1]

那么这个图的最长路径就转化的所有边的边权的最大值

现在就用一个数据结构去维护这些信息,支持删除,添加,最大

显然可以用堆,也可以用线段树

假设开始所有点都在T集中

按照拓扑序删点,并把该点加入S集中

把这个点有关的入边删掉,此时的最大值就是删当前点的答案,再把出边加入即可

Code

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<stack>
using namespace std;
void Freopen() {freopen("flower.in","r",stdin); freopen("flower.out","w",stdout);}
int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define MAXM 1000010
#define MAXN 500010
int N,M;
struct EdgeNode{int to,next;}edge[MAXM],road[MAXM];
int head[MAXN],cnt,last[MAXN],tot;
void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
void AddRoad(int u,int v) {tot++; road[tot].next=last[u]; last[u]=tot; road[tot].to=v;}
int topo[MAXN],tp,ind[MAXN],visit[MAXN],f[MAXN][];
void TopoSort()
{
int S=,T=N;
stack<int>st;
for (int i=S; i<=T; i++) if (!ind[i]) st.push(i),topo[++tp]=i;
while (!st.empty())
{
int now=st.top(); st.pop(); visit[now]=;
for (int i=head[now]; i; i=edge[i].next)
{
ind[edge[i].to]--;
if (!ind[edge[i].to]) st.push(edge[i].to),topo[++tp]=edge[i].to;
}
}
// printf("tp=%d\n",tp);
// for (int i=1; i<=tp; i++) printf("%d\n",topo[i]);
}
void GetLongestRoad()
{
for (int i=; i<=N; i++)
{
int now=topo[i];
f[now][]=max(f[now][],);
for (int j=head[now]; j; j=edge[j].next)
f[edge[j].to][]=max(f[edge[j].to][],f[now][]+);
}
for (int i=N; i>=; i--)
{
int now=topo[i];
f[now][]=max(f[now][],);
for (int j=head[now]; j; j=edge[j].next)
f[now][]=max(f[edge[j].to][]+,f[now][]);
}
}
struct SegmentTreeNode{int l,r,maxx,num;}tree[MAXN<<];
inline void Update(int now) {tree[now].maxx=max(tree[now<<].maxx,tree[now<<|].maxx);}
void BuildTree(int now,int l,int r)
{
tree[now].l=l,tree[now].r=r;
if (l==r) return;
int mid=(l+r)>>;
BuildTree(now<<,l,mid);
BuildTree(now<<|,mid+,r);
Update(now);
}
void Change(int now,int loc,int D)
{
int l=tree[now].l,r=tree[now].r;
if (l==r)
{tree[now].num+=D; tree[now].maxx=tree[now].num>? l:-; tree[now].num=max(tree[now].num,); return;}
int mid=(l+r)>>;
if (loc<=mid) Change(now<<,loc,D); else Change(now<<|,loc,D);
Update(now);
}
int Query(int now,int L,int R)
{
int l=tree[now].l,r=tree[now].r;
if (L<=l && R>=r) return tree[now].maxx;
int mid=(l+r)>>,re=-0x7fffffff;
if (L<=mid) re=max(re,Query(now<<,L,R));
if (R>mid) re=max(re,Query(now<<|,L,R));
return re;
}
int MaxLen,Pos;
int main()
{
// Freopen();
N=read(),M=read();
for (int x,y,i=; i<=M; i++)
x=read(),y=read(),AddEdge(x,y),AddRoad(y,x),ind[y]++;
TopoSort();
GetLongestRoad();
BuildTree(,,N);
MaxLen=0x7fffffff;
for (int i=; i<=N; i++) Change(,f[i][],);
for (int i=; i<=N; i++)
{
int now=topo[i];
Change(,f[now][],-);
for (int j=last[now]; j; j=road[j].next)
Change(,f[road[j].to][]+f[now][],-);
if (Query(,,N)<MaxLen) MaxLen=Query(,,N),Pos=now;
Change(,f[now][],);
for (int j=head[now]; j; j=edge[j].next)
Change(,f[now][]+f[edge[j].to][],);
}
printf("%d %d\n",Pos,MaxLen-);
return ;
}

【BZOJ-3832】Rally 拓扑序 + 线段树 (神思路题!)的更多相关文章

  1. 【BZOJ】4311: 向量(线段树分治板子题)

    题解 我们可以根据点积的定义,垂直于原点到给定点构成的直线作一条直线,从正无穷往下平移,第一个碰到的点就是答案 像什么,上凸壳哇 可是--动态维护上凸壳? 我们可以离线,计算每个点能造成贡献的一个询问 ...

  2. [BZOJ 2653] middle(可持久化线段树+二分答案)

    [BZOJ 2653] middle(可持久化线段树+二分答案) 题面 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序 ...

  3. codevs1228 (dfs序+线段树)

    1228 苹果树  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description 在卡卡的房子外面,有一棵苹果树.每年的春天,树上总会结 ...

  4. bzoj 3779 重组病毒 好题 LCT+dfn序+线段树分类讨论

    题目大意 1.将x到当前根路径上的所有点染成一种新的颜色: 2.将x到当前根路径上的所有点染成一种新的颜色,并且把这个点设为新的根: 3.查询以x为根的子树中所有点权值的平均值. 分析 原题codec ...

  5. DFS序+线段树(bzoj 4034)

    题目链接 题目就不多说了. 本题目,可以用dfs序+线段树做:题目给定了一棵树,树上节点告诉了权值.我们可以先将这棵树进行dfs将一棵树变成线性结构:如图 变成这样后,然后就可以用线段树. 操作1:也 ...

  6. BZOJ 3252题解(贪心+dfs序+线段树)

    题面 传送门 分析 此题做法很多,树形DP,DFS序+线段树,树链剖分都可以做 这里给出DFS序+线段树的代码 我们用线段树维护到根节点路径上节点权值之和的最大值,以及取到最大值的节点编号x 每次从根 ...

  7. Educational Codeforces Round 6 E dfs序+线段树

    题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...

  8. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] D ...

  9. Codeforces 343D Water Tree(DFS序 + 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

随机推荐

  1. 苹果IOS开发者账号的区别,企业账号,个人账号,公司团队账号,教育账号

    苹果IOS开发者账号总结 详细地址:https://developer.apple.com/programs/which-program/ 个人账号(Individual): 费用99美金一年, 该账 ...

  2. two sample ttest & paired ttst

    来源:http://www.pinzhi.org/thread-1023-1-1.html 成对t检验Paired Test是对来自同一总体的样本,在不同条件影响下获取的2组样本进行分析,以评价不同条 ...

  3. String PK StringBuilder,传说就是传说,只有动手实验,才能得出确定的答案

    本机测试结果如下: 大部分情况下,string 性能并不比StringBuilder差,只有特殊情况才出现差异,并非 如前面有些朋友测试的结果哪样,只要使用StringBuilder 就一定比Stri ...

  4. tcpip的可靠性

             

  5. 别出心裁的Linux系统调用学习法

    别出心裁的Linux系统调用学习法 操作系统与系统调用 操作系统(Operating System,简称OS)是计算机中最重要的系统软件,是这样的一组系统程序的集成:这些系统程序在用户对计算机的使用中 ...

  6. HoloLens开发手记 - Unity development overview 使用Unity开发概述

    Unity Technical Preview for HoloLens最新发行版为:Beta 24,发布于 09/07/2016 开始使用Unity开发HoloLens应用之前,确保你已经安装好了必 ...

  7. sdk墙内更新方法

    因为GFW有“保护”,我们能“安全”的遨游在中华互联局域网内.如何快速地更新sdk,一直是Android开发者的心病.网上流传着五花八门的方法,在这我记录一些我用过的切实可行的方法供给有需要的人.同时 ...

  8. Android Intent的几种用法全面总结

    Android Intent的几种用法全面总结 Intent, 用法 Intent应该算是Android中特有的东西.你可以在Intent中指定程序要执行的动作(比如:view,edit,dial), ...

  9. 替罪羊树模板(BZOJ1056/1862)

    #include<cstdio> #include<cstring> #include<cmath> #include<iostream> #defin ...

  10. python表达式操作符【学习python必知必会】

    运算符 描述 实例 yield x 生成器函数发送协议   lambda args: expression 生成匿名函数   x if y else z 三元选择表达式(c系列有的 python也要有 ...