题目描述

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。
请找到一个点,使得删掉这个点后剩余的图中的最长路径最短。

输入

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]有一条边。

输出

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后图中的最长路径的长度,如果有多组解请输出任意一组。

样例输入

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

样例输出

1 2
 
如果不删点求最长路很好求,直接拓扑排序求出每个点为起点的最长路取max即可。
但现在要求删点,那么就按拓扑序删点,删除经过删除点的最长路,也就是删除经过删除点的入边的最长路。
需要维护出以每个点为起点和终点的最长路,那么删除经过一条边(x,y)的最长路就是end[x]+1+start[y]。
每次删除点之后取一下剩下最长路中的最大值来更新答案。再将经过删除点出边的最长路加上就好了。
删点时只要用一个支持删除、插入、求最大值的数据结构即可。
那么为什么要按拓扑序删点?
因为只有按拓扑序删除插入才能保证不会删多或者删少。
如果随便顺序删除的话,可能一个点的入边只有一条,但经过这条入边的最长路却有很多条导致删少了。
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n,m;
int s[500010];
int t[500010];
int sum[4000010];
int p[500010];
int cnt;
int x,y;
int in[500010];
int out[500010];
vector<int>g[500010];
vector<int>h[500010];
queue<int>q;
int ans1,ans2;
void change(int rt,int l,int r,int k,int v)
{
if(l==r)
{
sum[rt]+=v;
return ;
}
int mid=(l+r)>>1;
if(k<=mid)
{
change(rt<<1,l,mid,k,v);
}
else
{
change(rt<<1|1,mid+1,r,k,v);
}
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
int query(int rt,int l,int r)
{
if(l==r)
{
return l;
}
int mid=(l+r)>>1;
if(sum[rt<<1|1]>0)
{
return query(rt<<1|1,mid+1,r);
}
else
{
return query(rt<<1,l,mid);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
out[x]++;
in[y]++;
g[x].push_back(y);
h[y].push_back(x);
}
for(int i=1;i<=n;i++)
{
if(!in[i])
{
q.push(i);
p[++cnt]=i;
}
}
while(!q.empty())
{
int now=q.front();
q.pop();
int len=g[now].size();
for(int j=0;j<len;j++)
{
in[g[now][j]]--;
s[g[now][j]]=max(s[g[now][j]],s[now]+1);
if(!in[g[now][j]])
{
q.push(g[now][j]);
p[++cnt]=g[now][j];
}
}
}
for(int i=1;i<=n;i++)
{
if(!out[i])
{
q.push(i);
}
}
while(!q.empty())
{
int now=q.front();
q.pop();
int len=h[now].size();
for(int j=0;j<len;j++)
{
out[h[now][j]]--;
t[h[now][j]]=max(t[h[now][j]],t[now]+1);
if(!out[h[now][j]])
{
q.push(h[now][j]);
}
}
}
int S=n+1;
int T=n+2;
for(int i=1;i<=n;i++)
{
g[i].push_back(T);
g[S].push_back(i);
h[i].push_back(S);
h[T].push_back(i);
change(1,0,n,t[i],1);
}
s[S]=-1;
t[T]=-1;
ans2=n+2;
for(int i=1;i<=cnt;i++)
{
int now=p[i];
int len=h[now].size();
for(int j=0;j<len;j++)
{
change(1,0,n,s[h[now][j]]+1+t[now],-1);
}
int res=query(1,0,n);
if(res<ans2)
{
ans2=res;
ans1=now;
}
len=g[now].size();
for(int j=0;j<len;j++)
{
change(1,0,n,s[now]+1+t[g[now][j]],1);
}
}
printf("%d %d\n",ans1,ans2);
}

BZOJ3832[Poi2014]Rally——权值线段树+拓扑排序的更多相关文章

  1. [bzoj3524==bzoj2223][Poi2014]Couriers/[Coci 2009]PATULJCI——主席树+权值线段树

    题目大意 给定一个大小为n,每个数的大小均在[1,c]之间的数列,你需要回答m个询问,其中第i个询问形如\((l_i, r_i)\),你需要回答是否存在一个数使得它在区间\([l_i,r_i]\)中出 ...

  2. HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并)

    layout: post title: HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并) author: "luowentaoaa&quo ...

  3. 【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings

    谁再管这玩意叫树状数组套主席树我跟谁急 明明就是树状数组的每个结点维护一棵动态开结点的权值线段树而已 好吧,其实只有一个指针,指向该结点的权值线段树的当前结点 每次查询之前,要让指针指向根结点 不同结 ...

  4. 【BZOJ-2892&1171】强袭作战&大sz的游戏 权值线段树+单调队列+标记永久化+DP

    2892: 强袭作战 Time Limit: 50 Sec  Memory Limit: 512 MBSubmit: 45  Solved: 30[Submit][Status][Discuss] D ...

  5. BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)

    题目大意:有一些位置.这些位置上能够放若干个数字. 如今有两种操作. 1.在区间l到r上加入一个数字x 2.求出l到r上的第k大的数字是什么 思路:这样的题一看就是树套树,关键是怎么套,怎么写.(话说 ...

  6. 动态求区间K大值(权值线段树)

    我们知道我们可以通过主席树来维护静态区间第K大值.我们又知道主席树满足可加性,所以我们可以用树状数组来维护主席树,树状数组的每一个节点都可以开一颗主席树,然后一起做. 我们注意到树状数组的每一棵树都和 ...

  7. 线段树(单标记+离散化+扫描线+双标记)+zkw线段树+权值线段树+主席树及一些例题

    “队列进出图上的方向 线段树区间修改求出总量 可持久留下的迹象 我们 俯身欣赏” ----<膜你抄>     线段树很早就会写了,但一直没有总结,所以偶尔重写又会懵逼,所以还是要总结一下. ...

  8. 【BZOJ3685】【zkw权值线段树】普通van Emde Boas树

    原题传送门 因为马上要开始搞树套树了,所以学了一波权值线段树...毕竟是会点zkw线段树的,所以zkw线段树大法好! 解题思路: 介绍一下权值线段树吧,其实感觉就是线段树的本义,就是你用线段树维护了数 ...

  9. BZOJ_2161_布娃娃_权值线段树

    BZOJ_2161_布娃娃_权值线段树 Description 小时候的雨荨非常听话,是父母眼中的好孩子.在学校是老师的左右手,同学的好榜样.后来她成为艾利斯顿第二 代考神,这和小时候培养的良好素质是 ...

随机推荐

  1. kubernetes 集群机器重启后磁盘盘符变化

    1.[root@pserver78 ~]# kubectl -n rook-ceph exec -it rook-ceph-tools-c95b8496b-g4stp -- ceph osd tree ...

  2. Skyline中的GDAL

    安装Skyline的TerraExplorer Pro软件后,我们很容易在其安装目录中找到这样一些文件: gdal.dll.gdal_csharp.dll.ogr_csharp.dll.osr_csh ...

  3. Dubbo与Zookeeper在Window上的安装与简单使用

    一:Dubbo是什么?有什么用途?? 使用Dubbo可以将应用分布到多个服务器上,当有访问时,Dubbo有帮你管理自动将请求分配给合适得到服务器去执行,即建立多个生产者,建立多个消费者,自动匹配生产者 ...

  4. C# 多线程 Parallel.For 和 For 谁的效率高?那么 Parallel.ForEach 和 ForEach 呢?

    还是那句话:十年河东,十年河西,莫欺少年穷. 今天和大家探讨一个问题:Parallel.For 和 For 谁的效率高呢? 从CPU使用方面而言,Parallel.For 属于多线程范畴,可以开辟多个 ...

  5. 基于Angular+WebAPI+OData的增删改查

    对于在ASP.NET WebAPI中怎么使用OData,已经在我前面的日志中的说明, 在ASP.NET Web API中使用OData 在这个示例中.我新建了一个Order的实体,在前端使用Angul ...

  6. 闭包----你所不知道的JavaScript系列(4)

    一.闭包是什么? · 闭包就是可以使得函数外部的对象能够获取函数内部的信息. · 闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. · 闭包就 ...

  7. Centos 6.9下部署Oracle 11G数据库环境的操作记录

    操作系统:Centos6.9(64Bit)Oracle:11g .11.2.0.4.0版本Ip地址:172.16.220.139 废话不多说了,下面记录安装过程:1)安装桌面环境 [root@vm01 ...

  8. Jmeter(GUI模式)教程

    前些天,领导让我做接口的压力测试.What??我从未接触过这方面,什么都不知道,一脸蒙.于是我从学习jmeter开始入手. 现在记录下来jmeter的使用步骤,希望能对大家有所帮助. 一.安装Jmet ...

  9. getUserMedia API及HTML5 调用摄像头和麦克风

    getUserMedia API简介 HTML5的getUserMedia API为用户提供访问硬件设备媒体(摄像头.视频.音频.地理位置等)的接口,基于该接口,开发者可以在不依赖任何浏览器插件的条件 ...

  10. Visual Studio2015安装过程以及单元测试

    安装环境: 安装版本: Visual Studio2015 安装过程: 因为我是在第一次老师安排的作业的时候感觉VC++6.0不如VS方便所以才装的Visual Studio2015,又安装了点插件, ...