轰炸行动(bomb):tarjan,拓扑排序
考场上看错题,没什么好说的。
然而它就是一个大板子。
发的题解勉强还能看。但是我还想再讲讲。
题目的表述是,如果从A能直接或间接到B,那么就不能同时轰炸A和B。
那么我们从图里随便拽出一条有向路径,从这条路径中随意挑2个点AB,那么要么能从A到B要么从B到A
那么你任意挑出的这两个点只要不是同一个点那么就不能同时轰炸。
带下划线的那一段有什么用呢?它的正确性是显然的。
我所说的“有向路径”没有加任何附加限制,所以可以包括环,环上转几圈就可能出现同一个点呗。
我们考虑单纯的一个环。那么它上的每一个都要单独炸一次。
再考虑单纯的一条路径,那么路径上的每一个点也需要单独炸一次。
如果一个路径进入了一个环,那么这上面的点也必须单独炸一次(路径上的点可以到达环上的任意点)。
如果一个环引出了一个路径,那么环上的点亦可到路径上,都要单独炸一次。
综上,就是要找出一条路径使它上面的不同的点尽量多,不同的点的个数即为答案。
上面那一堆话里已经包括了这个意思:环上的每个点都会给路径长度增加1,且对联通性没有影响。
所以考虑tarjan缩完强联通分量后就没有环了,只不过环变成了权值等于环中点数的一个大点而已
其余普通点的权值为1。现在的问题就变成了在一个DAG里找一条路径使它上面的点权和最大。
不能dfs,因为这是有向的DAG,虽然不是环但也不是树,它可以长得很恶心。
在这个恶心图里面跑dfs就会多次重复地经过3和3下面的点导致大量浪费。
可以倒着搜加个记忆化什么的,然而一个拓扑排序会更方便一些。
#include<bits/stdc++.h>
using namespace std;
map<int,int>mm;
int n,m,fir[],l[],to[],cnt=,dfn[],low[];
int _fir[],_l[],_to[],_cnt,w[],in[];
int sta[],ins[],tim,top,bl[],cnt_scc,ans,dis[];
int q[],t;
void connect(int a,int b){l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;}
void _connect(int a,int b){_l[++_cnt]=_fir[a];_fir[a]=_cnt;_to[_cnt]=b;in[b]++;}
void tarjan(int p){
dfn[p]=low[p]=++tim;sta[++top]=p;ins[p]=;
for(int i=fir[p];i;i=l[i])
if(!dfn[to[i]])tarjan(to[i]),low[p]=min(low[p],low[to[i]]);
else if(ins[to[i]])low[p]=min(low[p],low[to[i]]);
if(dfn[p]==low[p]){
w[++cnt_scc]++;
while(sta[top]!=p)ins[sta[top]]=,bl[sta[top--]]=cnt_scc,w[cnt_scc]++;
top--;bl[p]=cnt_scc;ins[p]=;
}
}
signed main(){
scanf("%d%d",&n,&m);
for(int i=,a,b;i<=m;++i)scanf("%d%d",&a,&b),connect(a,b);
for(int i=;i<=n;++i)if(!dfn[i])tarjan(i);
for(int i=;i<=n;++i)for(int j=fir[i];j;j=l[j])
if(bl[i]!=bl[to[j]])_connect(bl[i],bl[to[j]]);
for(int i=;i<=cnt_scc;++i)if(!in[i])q[++t]=i;
for(int h=;h<=t;++h){
int dt=dis[q[h]]+w[q[h]];ans=max(ans,dt);
for(int i=_fir[q[h]];i;i=_l[i]){
in[_to[i]]--;dis[_to[i]]=max(dis[_to[i]],dt);
if(!in[_to[i]])q[++t]=_to[i];
}
}
printf("%d\n",ans);
}
码量其实也不大
轰炸行动(bomb):tarjan,拓扑排序的更多相关文章
- 【bzoj1093】[ZJOI2007]最大半连通子图 Tarjan+拓扑排序+dp
题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:对于u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径. ...
- 【bzoj5017】[Snoi2017]炸弹 线段树优化建图+Tarjan+拓扑排序
题目描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆. 现在 ...
- 洛谷P1073 Tarjan + 拓扑排序 // 构造分层图
https://www.luogu.org/problemnew/show/P1073 C国有 n n个大城市和 mm 条道路,每条道路连接这 nn个城市中的某两个城市.任意两个城市之间最多只有一条道 ...
- bzoj 1093 最大半连通子图 - Tarjan - 拓扑排序 - 动态规划
一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G'=(V ...
- bzoj1093[ZJOI2007]最大半连通子图(tarjan+拓扑排序+dp)
Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u ...
- 【BZOJ2707】[SDOI2012]走迷宫 Tarjan+拓扑排序+高斯消元+期望
[BZOJ2707][SDOI2012]走迷宫 Description Morenan被困在了一个迷宫里.迷宫可以视为N个点M条边的有向图,其中Morenan处于起点S,迷宫的终点设为T.可惜的是,M ...
- 【tarjan 拓扑排序 dp】bzoj1093: [ZJOI2007]最大半连通子图
思维难度不大,关键考代码实现能力.一些细节还是很妙的. Description 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于 ...
- 【Luogu P3387】缩点模板(强连通分量Tarjan&拓扑排序)
Luogu P3387 强连通分量的定义如下: 有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶 ...
- P3387缩点(tarjan+拓扑排序+线性dp)
题目描述 给定一个 n个点 m 条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次. 输入 ...
- BZOJ 2208 JSOI2010 连通数 Tarjan+拓扑排序
题目大意:给定一个n个点的有向图,求有多少点对(x,y),使x沿边可到达y 设f[i][j]为从i到j是否可达 首先强联通分量中的随意两个点均可达 于是我们利用Tarjan缩点 缩点之后是一个拓扑图. ...
随机推荐
- xamarin开发的mac开发小工具集合
兄弟们我拖控件拖到了mac系统去了, 工具上传到百度网盘,下载地址 链接:https://pan.baidu.com/s/1Q64zoRjE3u66jJnzF8rhww提取码:ljx2 这款工具我是用 ...
- 使用LitePal建立表关联
关联关系的基础知识 喜欢把所有的代码都写在一个类里的程序员肯定是个新手.没错,任何一个像样的程序都不可能仅仅只有一个类的,同样地,任何一个像样的数据库也不可能仅仅只有一张表.我们都知道,在面向对象 ...
- angular4 httpclient拦截器
1.创建服务: InterceptorService.ts import { Injectable } from '@angular/core'; import { HttpEvent,HttpInt ...
- 选择高性能NoSQL数据库的5个步骤
来源:Redislabs作者:Shabih Syed 翻译:Kevin (公众号:中间件小哥) 构建在线和运营应用程序的开发团队越来越多地选择一类新的数据库来支持它们.它被称为“NoSQL”或“Not ...
- STM32进阶之串口环形缓冲区实现
队列的概念 在此之前,我们来回顾一下队列的基本概念: 队列 (Queue):是一种先进先出(First In First Out ,简称 FIFO)的线性表,只允许在一端插入(入队),在另一端进行删除 ...
- [CF494B] Obsessive String
Hamed has recently found a string t and suddenly became quite fond of it. He spent several days tryi ...
- spring在IoC容器中装配Bean详解
1.Spring配置概述 1.1.概述 Spring容器从xml配置.java注解.spring注解中读取bean配置信息,形成bean定义注册表: 根据bean定义注册表实例化bean: 将bean ...
- Java虚拟机类加载器及双亲委派机制
所谓的类加载器(Class Loader)就是加载Java类到Java虚拟机中的,前面<面试官,不要再问我"Java虚拟机类加载机制"了>中已经介绍了具体加载class ...
- 线性回归 python 代码实现
本代码参考自:https://github.com/lawlite19/MachineLearning_Python#%E4%B8%80%E7%BA%BF%E6%80%A7%E5%9B%9E%E5%B ...
- The usage of Markdown---文字强调:加粗/斜体/文本高亮/删除线/下划线/按键效果
更新时间:2019.09.14 1. 序言 有时候,我们需要对某些文字进行强调,例如粗体和斜体.而Markdown通常可以使用星号*或者下划线_进行文字强调. 2. 加粗 如果想要达到加粗的效果,可以 ...