【bzoj3832】Rally
Description
给你一个DAG,每条边长度都是\(1\),请找一个点满足删掉这个点之后剩余图中的最长路最短
Solution
这题的话感觉思路挺妙的
因为要涉及到删点操作,所以我们肯定不能通过直接的方法来算最长路,然后因为这题没有固定的起点和终点并且是一个DAG,所以有一个比较简单粗暴的处理方法就是像网络流一样建一个超级源\(S\)和一个超级汇\(T\),每个点都从\(S\)连一条长度为\(0\)的边,每个点都向\(T\)连一条长度为\(0\)的边
我们记\(f[i]\)表示从\(S\)到\(i\)点的最长路,记\(g[i]\)表示从\(i\)点到\(T\)点的最长路,这两个东西都可以按拓扑序转移直接dp出来(正反各来一次就好了),那么我们考虑一条边\((u,v)\)的贡献(也就是钦定要经过这条边的最长路)为\(f[u]+1+g[v]\),那么最长路的问题就变成了求边贡献的最大值
这个时候,考虑\(S\)到\(T\)的一个割(注意:这里不一定是最小割!只是一个普通的割即可),那么根据其定义,所有从\(S\)到\(T\)的路径必定经过割集中的最少一条边,也就是说,如果我们将\(f[u]+1+g[v]\)看成原图中\((u,v)\)这条边的边权,将\((S,i)\)的边权看成\(f[i]\),\((i,T)\)的边权看成\(g[i]\),割集中边权的最大值便是我们需要的答案
那么现在我们只要知道删掉一个点之后,剩余图中\(S\)到\(T\)的一个割就可以知道删掉这个点的答案了,至此我们已经完成了问题的转化,现在的问题是我们怎么维护这个割集
我们考虑用一个数据结构来快速获得边权最大值(线段树或者堆都ok)
假设一开始我们先把所有的\((i,T)\)的边全部断掉(这显然是一个可行的割),也就是先将所有的\(g[i]\)丢进数据结构里面,现在考虑删掉一个点\(x\)的影响:所有拓扑序在\(x\)之后的点的\(f\)值可能会被影响,所有拓扑序在\(x\)之前的点的\(g\)值可能会被影响,这个时候为了保证正确性我们应该将当前割集中可能会被改变边权的边全部删掉
但是这样怎么保证当前最大值一定在数据结构里面呢?这里需要一点关于操作顺序的技巧,下面先将过程讲一下:
我们考虑按照拓扑序从小到大依次计算删除这个点之后的最长路,对于当前枚举到的点\(x\),我们进行如下操作:
1、将\((x,T)\)这条边删掉,将所有的\((u,x)\)删掉(如果本来就没有就不进行操作)
2、统计当前割集中边权的最大值,更新答案
3、将\((S,x)\)这条边加入割集,将所有的\((x,v)\)加入割集
具体一点的话就是,首先\(1\)操作就是将割集中所有与\(x\)有关的边全部删掉,\(2\)不用说,关键是\(3\)操作,为什么我们还原割集的时候不是将\(1\)操作中删除的边加回进去呢?
因为我们是按照拓扑序从小到大删点的,根据我们前面分析出来的删点影响,在删除后面的点的时候,\(g[x]\)是可能会被影响的值(转移过来的边可能会被删掉),因此为了保证正确性我们不能将其留在割集中,同时为了保证这是一个割集,相对应的边权不会被影响到并且效果类似的\((S,x)\)就应该被加入割集,同样的道理\((u,x)\)的边权中的\(g[x]\)可能会被影响所以要删掉,然后为了保证一定是一个割集所以要加入\((x,v)\)这类边
那么会不会出现有的边的贡献作为答案没有被统计的情况呢?这个。。是不会的因为如果说\((u,x)\)这类边的贡献是答案的话,一定会在前面被计算到
然后这题就十分愉快地做完啦ovo时间复杂度\(O(nlogn)\)
代码大概长这个样子
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int N=500010,M=1000010,SEG=N*4,inf=2147483647;
struct xxx{
int y,nxt;
}a[M*2];
queue<int> q;
int h1[N],h[N],in[N],out[N],f[N],g[N];
int rec[N];
int n,m,tot,ans,ansnode;
namespace Seg{/*{{{*/
int ch[SEG][2],mx[SEG],cnt[SEG];
int n,tot;
void pushup(int x){mx[x]=max(mx[ch[x][0]],mx[ch[x][1]]);}
void _build(int x,int l,int r){
mx[x]=-1;
if (l==r) return;
int mid=l+r>>1;
ch[x][0]=++tot; _build(ch[x][0],l,mid);
ch[x][1]=++tot; _build(ch[x][1],mid+1,r);
}
void build(int _n){tot=1; n=_n; _build(1,1,n);}
void _insert(int x,int d,int lx,int rx,int delta){
if (lx==rx){
cnt[x]+=delta;
if (cnt[x]>0) mx[x]=lx;
else cnt[x]=0,mx[x]=-1;
return;
}
int mid=lx+rx>>1;
if (d<=mid) _insert(ch[x][0],d,lx,mid,delta);
else _insert(ch[x][1],d,mid+1,rx,delta);
pushup(x);
}
void insert(int d,int delta){_insert(1,d,1,n,delta);}
int query(){return mx[1];}
}/*}}}*/
void add(int x,int y){
a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot;
a[++tot].y=x; a[tot].nxt=h1[y]; h1[y]=tot;
}
void prework(){
int u,v;
while (!q.empty()) q.pop();
for (int i=1;i<=n;++i)
if (!in[i]) q.push(i),f[i]=0;
rec[0]=0;
while (!q.empty()){
v=q.front(); q.pop(); rec[++rec[0]]=v;
for (int i=h[v];i!=-1;i=a[i].nxt){
u=a[i].y;
f[u]=max(f[u],f[v]+1);
--in[u];
if (!in[u]) q.push(u);
}
}
for (int i=1;i<=n;++i)
if (!out[i]) q.push(i),g[i]=0;
while (!q.empty()){
v=q.front(); q.pop();
for (int i=h1[v];i!=-1;i=a[i].nxt){
u=a[i].y;
g[u]=max(g[u],g[v]+1);
--out[u];
if (!out[u]) q.push(u);
}
}
}
void solve(){
int x,u,tmp;
ans=inf; ansnode=0;
Seg::build(n+1);
for (int i=1;i<=n;++i) Seg::insert(g[i]+1,1);
for (int i=1;i<=n;++i){
x=rec[i];
Seg::insert(g[x]+1,-1);
for (int j=h1[x];j!=-1;j=a[j].nxt){
u=a[j].y;
Seg::insert(f[u]+1+g[x]+1,-1);
}
tmp=Seg::query();
if (ans>tmp)
ans=tmp,ansnode=x;
Seg::insert(f[x]+1,1);
for (int j=h[x];j!=-1;j=a[j].nxt){
u=a[j].y;
Seg::insert(f[x]+1+g[u]+1,1);
}
}
printf("%d %d\n",ansnode,ans-1);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
int x,y;
scanf("%d%d",&n,&m);
memset(h,-1,sizeof(h));
memset(h1,-1,sizeof(h1));
tot=0;
for (int i=1;i<=m;++i){
scanf("%d%d",&x,&y);
add(x,y);
++in[y]; ++out[x];
}
prework();
solve();
}
【bzoj3832】Rally的更多相关文章
- 【BZOJ-3832】Rally 拓扑序 + 线段树 (神思路题!)
3832: [Poi2014]Rally Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 168 Solved: ...
- 【BZOJ3832】[POI2014]Rally(拓扑排序,动态规划)
[BZOJ3832][POI2014]Rally(拓扑排序,动态规划) 题面 BZOJ,权限题 洛谷 题解 这题好强啊,感觉学了好多东西似的. 首先发现了一个图画的很好的博客,戳这里 然后我来补充一下 ...
- Python高手之路【六】python基础之字符串格式化
Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...
- 【原】谈谈对Objective-C中代理模式的误解
[原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...
- 【原】FMDB源码阅读(三)
[原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
- 【调侃】IOC前世今生
前些天,参与了公司内部小组的一次技术交流,主要是针对<IOC与AOP>,本着学而时习之的态度及积极分享的精神,我就结合一个小故事来初浅地剖析一下我眼中的“IOC前世今生”,以方便初学者能更 ...
- Python高手之路【三】python基础之函数
基本数据类型补充: set 是一个无序且不重复的元素集合 class set(object): """ set() -> new empty set object ...
- Python高手之路【一】初识python
Python简介 1:Python的创始人 Python (英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/), 是一种解释型.面向对象.动态数据类型的高级程序设计语言,由荷兰人Guido ...
随机推荐
- 【CentOS 7】nginx配置web服务器
1,安装过程 [root@VM_1_14_centos ~]# cd /data/ [root@VM_1_14_centos data]# wget http://nginx.org/download ...
- fetch err : "Body not allowed for GET or HEAD requests"
在使用 fetch 的时候 报了 "Body not allowed for GET or HEAD requests" 这个错. 代码如下: 一番google , 找到答案了. ...
- ORM PHP 学习记录
ORM:object relation mapping,即对象关系映射,简单的说就是对象模型和关系模型的一种映射.为什么要有这么一个映射?很简单,因为现在的开发语言基本都是oop的,但是传统的数据库却 ...
- 2017年软件工程第十二次作业-PSP总结报告
回顾1 1.回想一下你曾经对计算机专业的畅想 当初你是如何做出选择计算机专业的决定的?经过一个学期,你的看法改变了么,为什么? 你认为过去接触到的课程是否符合你对计算机专业的期待,为什么?经过一个学期 ...
- Daily Scrum 1 --团队项目所需时间估计以及任务分配
考虑到所有的任务不可能逐一细化分配给成员,我们将需要完成的任务进行了大致的分配.任务所需要的具体实现可以参看<学霸网站NABC> 所需要的总时间一共为44h. 我们会在以后的每日任务中进行 ...
- 面向对象OO第1-3次作业总结
面向对象OO第1-3次作业总结 学习OO已经四周了,对OO以及JAVA的编程也算终于了解了一丢丢.现在做完了三次的编程作业,对前三次的作业做一次总结. 第一次作业 ------------------ ...
- 对JAVA RMI的认识
RMI的定义 RPC (Remote Procedure Call):远程方法调用,用于一个进程调用另一个进程中的过程,从而提供了过程的分布能力. RMI(Remote Method Invocati ...
- 基于Freemarker的eclipse plugin代码生成器插件开发
固定类型的软件写多了,里面总是有一些复制粘贴改变类名改变量的基础文件,相似程度非常高.作为一名程序员,坚持不多写一行重复代码的精神,写了一个Eclipse的代码生成器插件.插件通过在xml文件中配置的 ...
- Find non-overlap jobs with max cost
Given a set of n jobs with [start time, end time, cost] find a subset so that no 2 jobs overlap and ...
- Intellij IDEA Scala开发环境搭建
1,在intellij 官网上下载IDEA 2,在scala官网上下载最新版scala 3,安装两个下载的文件 4,打开intellij,菜单栏help->find action 输入plu ...