洛谷 P3573 [POI2014]RAJ-Rally 解题报告
P3573 [POI2014]RAJ-Rally
题意:
给定一个\(N\)个点\(M\)条边的有向无环图,每条边长度都是\(1\)。
请找到一个点,使得删掉这个点后剩余的图中的最长路径最短。
输入输出格式
输入格式:
第一行包含两个正整数\(N\),\(M\),表示点数、边数。
接下来\(M\)行每行包含两个正整数\(A_i,B_i\),表示\(A_i\)到\(B_i\)有一条边。
输出格式:
包含一行两个整数\(x,y\),用一个空格隔开,\(x\)为要删去的点,\(y\)为删除x$后图中的最长路径的长度,如果有多组解请输出任意一组。
说明:
\(N,M(2 \le N \le 500000,1 \le M \le 1000000)\)
好神仙的一道题目!
一般来说一些删边删点的东西在统计统计信息什么的在图上都比较麻烦,我们应该找一找这个题的特殊性
很容易发现,重点在这个图是DAG。
有了DAG,我们可以\(O(n)\)求出单源点最长路什么的
然而这个图的最长路咋求呢?其实这个不难,统计通过每条边的最长路,取最大值就行了
设\(diss_i\)表示以\(i\)为开头的最长路,\(dist_i\)表示以\(i\)为结尾的最长路,为起点的反向跑一遍就可以得到
通过某条边\(E=(u,v)\)的最长路等价于\(dist_u+diss_v+1\)
topo图还有一个性质,按照topo序取出一部分连续的点作为\(S\)集,剩下的作为\(T\)集,则两个集合的相互连边只有一些\(S\)到\(T\)的
为了方便,节点编号就是topo序,红边为\(S\)连向\(T\)的边
这启发我们按照拓扑序进行删点,我们先假设所有的点在\(T\)集,这样最长路就是\(max diss_i\)
我们按topo序拿走点,删掉有关贡献的边,统计答案,加入有关贡献的边,然后加入\(S\)集
这样说起来一点也不清楚,我们结合图形说明
现在正在删点4,看看有那些边可以作为答案。
首先\(S\)集合里面的边的最长长度,但不可以跨越两个集合即 \(max_{i \in S} dist_i\),当然4的不算
然后跨越\(S,T\)集合的边即 \(max_{E(u,v),u \in S,v \in T} dist_u+diss_v+1\)
最后是集合\(T\)的,其实也差不多,不赘述了
我们首先在\(T\)集合的只有最后一种的答案,发现第一种的答案可以在把点扔进\(S\)的时候更新,而多余的\(T\)的答案可以在每次删点时删掉
第二种边其实也好统计,在点进去的时候出边都放进答案,当这个出边对的点进入\(S\)的时候把边的答案去掉
这么说可能还是有点抽象,还是拿4举个例子
第一步,删去\(diss_4\)
第二步,删去\(diss_4+dist_{1/2/3}+1\)这三个
第三步,统计最大值
第四步,加入\(dist_4+diss_{6/7}+1\)这两个
第五步,加入\(dist_4\)
关于这些操作,因为边权很小,所以我们可以拿权值线段树维护,也可以拿堆维护
其实思想上我说得也不算清楚,只是大概把过程讲清楚了
Code:
#include <cstdio>
#include <vector>
const int N=1e6+10;
int head[N],to[N<<1],Next[N<<1],cnt;
void add(int u,int v)
{
to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
}
std::vector <int > To[N];
int q[N],n,m,in[N],topo[N],tot;
void toposort()
{
int l=1,r=0;
for(int i=1;i<=n;i++)
if(!in[i]) topo[++tot]=i,q[++r]=i;
while(l<=r)
{
int u=q[l++];
for(int i=head[u];i;i=Next[i])
{
int v=to[i];
--in[v];
if(!in[v]) q[++r]=v,topo[++tot]=v;
}
}
}
int diss[N],dist[N];
#define ls ch[now][0]
#define rs ch[now][1]
int max(int x,int y){return x>y?x:y;}
void DP()
{
for(int k=1;k<=n;k++)
{
int u=topo[k];
for(int i=head[u];i;i=Next[i])
{
int v=to[i];
dist[v]=max(dist[v],dist[u]+1);
}
}
for(int k=n;k;k--)
{
int u=topo[k];
for(int i=0;i<To[u].size();i++)
{
int v=To[u][i];
diss[v]=max(diss[v],diss[u]+1);
}
}
}
void init()
{
scanf("%d%d",&n,&m);
for(int u,v,i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
add(u,v),++in[v],To[v].push_back(u);
}
toposort();
DP();
}
int ch[N<<2][2],sum[N<<2],root;
void change(int &now,int l,int r,int pos,int delta)
{
if(!now) now=++tot;
if(l==r) {sum[now]+=delta;return;}
int mid=l+r>>1;
if(pos<=mid) change(ls,l,mid,pos,delta);
else change(rs,mid+1,r,pos,delta);
sum[now]=sum[ls]+sum[rs];
}
int query(int now,int l,int r)
{
if(l==r) return l;
int mid=l+r>>1;
if(sum[rs]) return query(rs,mid+1,r);
else return query(ls,l,mid);
}
void work()
{
tot=0;int mx,id,ans=0x7fffffff;
for(int i=1;i<=n;i++)
change(root,0,n,diss[i],1);
for(int i=1;i<=n;i++)
{
int now=topo[i];
change(root,0,n,diss[now],-1);
for(int j=0;j<To[now].size();j++)
{
int v=To[now][j];
change(root,0,n,diss[now]+dist[v]+1,-1);
}
if((mx=query(root,0,n))<ans) ans=mx,id=now;
for(int j=head[now];j;j=Next[j])
{
int v=to[j];
change(root,0,n,dist[now]+diss[v]+1,1);
}
change(root,0,n,dist[now],1);
}
printf("%d %d\n",id,ans);
}
int main()
{
init(),work();
return 0;
}
2018.9.7
洛谷 P3573 [POI2014]RAJ-Rally 解题报告的更多相关文章
- 洛谷_Cx的故事_解题报告_第四题70
1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h> struct node { long x,y,c; ...
- 洛谷 P2317 [HNOI2005]星际贸易 解题报告
P2317 [HNOI2005]星际贸易 题目描述 输入输出格式 输入格式: 输出格式: 如果可以找到这样的方案,那么输出文件output.txt中包含两个整数X和Y.X表示贸易额,Y表示净利润并且两 ...
- 洛谷 P3802 小魔女帕琪 解题报告
P3802 小魔女帕琪 题目背景 从前有一个聪明的小魔女帕琪,兴趣是狩猎吸血鬼. 帕琪能熟练使用七种属性(金.木.水.火.土.日.月)的魔法,除了能使用这么多种属性魔法外,她还能将两种以上属性组合,从 ...
- 洛谷 P2606 [ZJOI2010]排列计数 解题报告
P2606 [ZJOI2010]排列计数 题目描述 称一个\(1,2,...,N\)的排列\(P_1,P_2...,P_n\)是\(Magic\)的,当且仅当对所以的\(2<=i<=N\) ...
- 洛谷1303 A*B Problem 解题报告
洛谷1303 A*B Problem 本题地址:http://www.luogu.org/problem/show?pid=1303 题目描述 求两数的积. 输入输出格式 输入格式: 两个数 输出格式 ...
- 【刷题】洛谷 P3573 [POI2014]RAJ-Rally
题目描述 An annual bicycle rally will soon begin in Byteburg. The bikers of Byteburg are natural long di ...
- 洛谷 P3084 [USACO13OPEN]照片Photo 解题报告
[USACO13OPEN]照片Photo 题目描述 农夫约翰决定给站在一条线上的\(N(1 \le N \le 200,000)\)头奶牛制作一张全家福照片,\(N\)头奶牛编号\(1\)到\(N\) ...
- 洛谷 P1379 八数码难题 解题报告
P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初 ...
- NOIP2015 D2T3 洛谷2680 BZOJ4326 运输计划 解题报告
前言:个人认为这是历年NOIP中比较简单的最后一题了,因此将自己的思路与大家分享. 题目大意: 给一棵无根树,给出m条路径.允许将树上的一条边的权值改为0.求m条路径长度最大值的最小值.n,m< ...
随机推荐
- IDEA的下载安装和激活
1.下载网站http://www.jetbrains.com/ 2. 3. 4.注意要下载Ultimate版本 5.安装 下载完成后直接下一步,傻瓜式安装 6.激活,在图片位置输入激活码即可 !!!! ...
- 解决scp命令pemission denied,please try again的问题
问题描述:输入命令scp a.txt root@192.168.0.105:/tmp(将当前目录下的文件a.txt复制到服务器IP为192.168.0.105的root用户的/tmp/目录下),结果会 ...
- 浏览器进程/线程模型及JS运行机制
浏览器是多进程的,有一个主控进程,以及每一个tab页面都会新开一个进程(某些情况下多个tab会合并进程). 进程可能包括主控进程,插件进程,GPU,tab页(浏览器内核)等等. Browser进程:浏 ...
- openwrt(一):openwrt源码下载及编译环境搭建
声明:从网上各位大神的博客学习,整理后记录,非原创. 注:请用非root用户来下载源码 导航: 1. openwrt编译环境搭建 2. openwrt源码下载 3. feeds更新 1. openwr ...
- 队列--数据结构与算法JavaScript描述(5)
队列 Queue 概念 队列是一种列表,但队列只能在队尾插入元,在队首删除元素. 队列是一种先进先出的数据结构,用于存储按顺序排列的数据,被用在很多地方,比如提交操作系统执行的一系列进程.打印任务池等 ...
- IIS发布错误记录
1.HTTP 错误 500.19 - Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效. 详细错误信息模块 IIS Web Core 通知 BeginRequ ...
- webstorm git提交不成功的
git pull git pull origin master git pull origin master --allow-unrelated-histories
- Hyper-V在线调整虚拟硬盘大小
从Windows Server 2012 R2 开始,可以在线调整虚拟硬盘的大小了,这意味着当虚拟硬盘不够用时,我们在虚拟机运行的情况下直接扩展虚拟硬盘容量了.有人说这个有什么用?当然,实验室情况下, ...
- Android学习笔记(一)之仿正点闹钟时间齿轮滑动的效果
看到正点闹钟上的设置时间的滑动效果非常好看,自己就想做一个那样的,在网上就开始搜资料了,看到网上有的齿轮效果的代码非常多,也非常难懂,我就决定自己研究一下,现在我就把我的研究成果分享给大家.我研究的这 ...
- 从事IT业一个8年老兵转行前的自我总结2——从《易经》说开来
近些年一直在读<易经>,收获颇多.以前看不贯的人或物现在可以淡然看定,以前看不开的一些事现在也安然放下,以前看不透的某些事现在也都可看透八九不离十. 古人云:不读<易>不可为将 ...