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 解题报告的更多相关文章

  1. 洛谷_Cx的故事_解题报告_第四题70

    1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h>   struct node {     long x,y,c; ...

  2. 洛谷 P2317 [HNOI2005]星际贸易 解题报告

    P2317 [HNOI2005]星际贸易 题目描述 输入输出格式 输入格式: 输出格式: 如果可以找到这样的方案,那么输出文件output.txt中包含两个整数X和Y.X表示贸易额,Y表示净利润并且两 ...

  3. 洛谷 P3802 小魔女帕琪 解题报告

    P3802 小魔女帕琪 题目背景 从前有一个聪明的小魔女帕琪,兴趣是狩猎吸血鬼. 帕琪能熟练使用七种属性(金.木.水.火.土.日.月)的魔法,除了能使用这么多种属性魔法外,她还能将两种以上属性组合,从 ...

  4. 洛谷 P2606 [ZJOI2010]排列计数 解题报告

    P2606 [ZJOI2010]排列计数 题目描述 称一个\(1,2,...,N\)的排列\(P_1,P_2...,P_n\)是\(Magic\)的,当且仅当对所以的\(2<=i<=N\) ...

  5. 洛谷1303 A*B Problem 解题报告

    洛谷1303 A*B Problem 本题地址:http://www.luogu.org/problem/show?pid=1303 题目描述 求两数的积. 输入输出格式 输入格式: 两个数 输出格式 ...

  6. 【刷题】洛谷 P3573 [POI2014]RAJ-Rally

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

  7. 洛谷 P3084 [USACO13OPEN]照片Photo 解题报告

    [USACO13OPEN]照片Photo 题目描述 农夫约翰决定给站在一条线上的\(N(1 \le N \le 200,000)\)头奶牛制作一张全家福照片,\(N\)头奶牛编号\(1\)到\(N\) ...

  8. 洛谷 P1379 八数码难题 解题报告

    P1379 八数码难题 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给出一种初始布局(初 ...

  9. NOIP2015 D2T3 洛谷2680 BZOJ4326 运输计划 解题报告

    前言:个人认为这是历年NOIP中比较简单的最后一题了,因此将自己的思路与大家分享. 题目大意: 给一棵无根树,给出m条路径.允许将树上的一条边的权值改为0.求m条路径长度最大值的最小值.n,m< ...

随机推荐

  1. CSU 1216异或最大值 (0-1 trie树)

    Description 给定一些数,求这些数中两个数的异或值最大的那个值 Input 多组数据.第一行为数字个数n,1 <= n <= 10 ^ 5.接下来n行每行一个32位有符号非负整数 ...

  2. UVA_1434_YAPTCHA

    The math department has been having problems lately. Due to immense amount of unsolicited automated ...

  3. activemq启动闪退/失败 (Illegal character in hostname at index 5: ws://****:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600)

    java.net.URISyntaxException: Illegal character in hostname at index 5: ws://****:61614?maximumConnec ...

  4. 基于PHP的微信公众平台开发(TOKEN验证,消息回复)

    微信公众平台开发 实现步骤: 第一步:填写服务器配置 登录微信公众平台官网后,在公众平台后台管理页面 - 开发者中心页,点击“修改配置”按钮,填写服务器地址(URL).Token和EncodingAE ...

  5. tomcat日志切割脚本

    tomcat日志每俩小时切割的脚本如下(这是用定时任务来完成的,此方法无需重启tomcat): time=$(date +%H) end_time=`` a=$end_time BF_TIME=$(- ...

  6. linux下Tomcat配置提示权限不够解决办法

    在终端输入命令 sudo chmod -R 777 /opt/Tomcat,那么Tomcat文件夹和它下面的所有子文件夹的属性都变成了777(读/写/执行权限)

  7. select值改变

    改变select的值,然后执行一个方法.可以用chang: $("#select").change(function(){ //要执行的内容 });

  8. python3 练习题100例 (十九)

    #!/usr/bin/env python3 # -*- coding: utf-8 -*- """练习十九:计算1-2+3...+99中除了88以外所有数的和" ...

  9. MongoDB的Go语言驱动注意点

    当我们定义一个struct用来和集合对应时,要注意结构体的字段首字母应该大写,不然不可见. 通过`bson:"name"`这种方式可以定义MongoDB中集合的字段名,如果不定义, ...

  10. saltstack特点

    目录 saltstack特点 saltstack特点 实时交互 所有的minion机器同时执行命令 no freeloader 每一台salt minion上都装有执行master传来的命令所需要的程 ...