8.10-DayT3游走(wander)
题目大意
lue..
题解
先跑一遍tarjan缩点,在新图中加入两个强连通分量之间的边,则此图为一个有向无环图(DAG)。则最终答案为1点所在的强连通分量或包括1点的几个强连通分量的点数之和。
如果为几个强连通分量则由于该图为DAG而题中要求为从1点出发又回到1点,
故路径中一定包含一条反向边。又由于强连同分量中的点彼此强连同,故该反向边一定为两个强连同分量之间的边。
故路径为一条边+一条经过一点所在强连通分量的路径。
图中每个点代表一个强连通分量。其中1为包含1点的强通分量。
其中路径为k-->........3-->1-->2-->4-->......-->n,而反向边为边k-->n
因此,最终答案即为求如上一条包含点最多的路径。
考虑边k-->n,边k-->n一定为缩点后强连通分量之间的边。如果首先求出路径长度则枚举边k-->n即可。而路径长度一定为k-->1的包含点最多的路径长度与1-->n的包含点最多的路径的点的个数之和减1点所在的强连通分量包含的点的个数。
故可以预处理出1点所在的强连通分量到其他强连通分量的路径中最多包含点的个数,再将所有强连通分量间的边反向,求1点所在的强连通分量到其他强连通分量的路径中最多包含点的个数,既求其他强连通分量到1点所在的强连通分量的路径中最多包含点的个数。
最后枚举所有强连通分量之间的边k-->n,答案为 max(f1[n]+f2[k]-size[bel[1]])
注意:当f1或f2为0时不更新答案因为如果为0则代表1点所在的强连通分量
无法到达n点或k点。
Tarjan时间复杂度为O(n+m),两次DAG上求最长路的时间复杂度为O(m)
总体时间复杂度O(n+m)。
(hhh一看就不是我自己写的题解...改不动了hhh)
#include<stack>
#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 110000
int n,m,ans;
int t1,t2,tot,scc,cnt;
int head[N],to[*N],nex[*N];
int deep[N],low[N],bel[N],vis[N];
int ins[N],inq[N],size[N];
int f1[N],f2[N];
stack<int>s;
queue<int>que;
void add(int x,int y)
{
tot++;
nex[tot]=head[x];
head[x]=tot;
to[tot]=y;
}
int tot1;
int head1[N],to1[*N],nex1[*N],from1[*N];
void add1(int x,int y)
{
tot1++;
nex1[tot1]=head1[x];
head1[x]=tot1;
to1[tot1]=y;
from1[tot1]=x;
}
int tot2;
int head2[N],to2[*N],nex2[*N],from2[*N];
void add2(int x,int y)
{
tot2++;
nex2[tot2]=head2[x];
head2[x]=tot2;
to2[tot2]=y;
from2[tot2]=x;
}
void tarjan(int x)
{
deep[x]=low[x]=++cnt;
ins[x]=;
vis[x]=;
s.push(x);
for(int i=head[x];i;i=nex[i])
{
if(ins[to[i]])
low[x]=min(low[x],deep[to[i]]);
else if(!vis[to[i]])
{
tarjan(to[i]);
low[x]=min(low[x],low[to[i]]);
}
}
if(deep[x]==low[x])
{
scc++;
int tmp=s.top();
s.pop();
size[scc]++;
bel[tmp]=scc;
ins[tmp]=;
while(tmp!=x)
{
tmp=s.top();
s.pop();
size[scc]++;
ins[tmp]=;
bel[tmp]=scc;
}
}
}
int main()
{
freopen("wander.in","r",stdin);
freopen("wander.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
scanf("%d%d",&t1,&t2);
add(t1,t2);
}
for(int i=;i<=n;i++)
{
if(!vis[i])
{
cnt=;
tarjan(i);
}
}
for(int i=;i<=n;i++)
{
for(int j=head[i];j;j=nex[j])
if(bel[i]!=bel[to[j]])
{
add1(bel[i],bel[to[j]]);
add2(bel[to[j]],bel[i]);
}
}
que.push(bel[]);
f1[bel[]]=size[bel[]];
inq[bel[]]=;
while(!que.empty())
{
int tmp=que.front();
que.pop();
inq[tmp]=;
for(int i=head1[tmp];i;i=nex1[i])
if(f1[to1[i]]<f1[tmp]+size[to1[i]])
{
f1[to1[i]]=f1[tmp]+size[to1[i]];
if(!inq[to1[i]])
{
inq[to1[i]]=;
que.push(to1[i]);
}
}
}
memset(inq,,sizeof(inq));
que.push(bel[]);
inq[bel[]]=;
f2[bel[]]=size[bel[]];
while(!que.empty())
{
int tmp=que.front();
que.pop();
inq[tmp]=;
for(int i=head2[tmp];i;i=nex2[i])
if(f2[to2[i]]<f2[tmp]+size[to2[i]])
{
f2[to2[i]]=f2[tmp]+size[to2[i]];
if(!inq[to2[i]])
{
inq[to2[i]]=;
que.push(to2[i]);
}
}
}
ans=max(ans,size[bel[]]);
for(int i=;i<=tot2;i++)
if(f2[to2[i]]&&f1[from2[i]])
{
if(f2[to2[i]]+f1[from2[i]]-size[bel[]]>ans)
ans=f2[to2[i]]+f1[from2[i]]-size[bel[]];
}
printf("%d",ans);
return ;
}
std太强了
8.10-DayT3游走(wander)的更多相关文章
- 【BZOJ-3143】游走 高斯消元 + 概率期望
3143: [Hnoi2013]游走 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2264 Solved: 987[Submit][Status] ...
- 3143: [Hnoi2013]游走 - BZOJ
Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点, ...
- bzoj 3143: [Hnoi2013]游走 高斯消元
3143: [Hnoi2013]游走 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1026 Solved: 448[Submit][Status] ...
- 数学(概率):HNOI2013 游走
[题目描述] 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这 ...
- 介绍一个全局最优化的方法:随机游走算法(Random Walk)
1. 关于全局最优化求解 全局最优化是一个非常复杂的问题,目前还没有一个通用的办法可以对任意复杂函数求解全局最优值.上一篇文章讲解了一个求解局部极小值的方法--梯度下降法.这种方法对于求解精度不高 ...
- [补档][Hnoi2013]游走
[Hnoi2013]游走 题目 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一 ...
- 游走[HNOI2013]
[题目描述] 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这 ...
- bzoj 3143: [Hnoi2013]游走
Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点, ...
- BZOJ 3143: [Hnoi2013]游走 [概率DP 高斯消元]
一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分 ...
随机推荐
- 【巨杉数据库SequoiaDB】SequoiaDB 巨杉数据库 v3.4 版本正式发布
深秋时节,SequoiaDB 巨杉数据库在深秋给大家带来了“一把火”.SequoiaDB v3.4 正式发布啦! 分布式交易场景性能大幅提升 SequoiaDB 巨杉数据库3.4版本正式发布,v3.4 ...
- 多个iframe,删除详情页时刷新同级iframe的table list
说明:在使用iframe开发时,经常遇到多个iframe之间的操作. 下面就是一个需求:在一个iframe中关闭时,刷新指定的iframe: 添加需要刷新的标识reload=true //添加npi2 ...
- Docker最全教程——从理论到实战(十)
终于按时完成第二篇.本来准备着手讲一些实践,但是数据库部分没有讲到,部分实践会存在一些问题,于是就有了此篇以及后续——数据库容器化.本篇将从SQL Server容器化实践开始,并逐步讲解其他数据库的容 ...
- python 深浅copy总结
总结: ''' 总结:假设l1为原数据,l2为deepcopy后的数据: 1.浅copy,只能改变第一层的内存地址(不可变数据类型除外). 2.深copy,能够改变第一层和第二层的内存地址(不可变数据 ...
- AcWing 187. 导弹防御系统
//dp+dfs+贪心 //记一个全局变量 #include<iostream> using namespace std ; ; int n; int ans; int q[N]; int ...
- dev、test、pre和prod是什么意思?
开发环境(dev):开发环境是程序猿们专门用于开发的服务器,配置可以比较随意,为了开发调试方便,一般打开全部错误报告. 测试环境(test):一般是克隆一份生产环境的配置,一个程序在测试环境工 ...
- NVMe over Fabrics 概况
NVMe over Fabrics 技术特征 跨网络传输NVMe命令需要特殊的考虑,而不仅仅是针对本地存储内存.例如,为了远距离传输NVMe协议,理想的底层网络或fabric技术将具有以下特性: 可靠 ...
- 剑指offer系列——59/60.按之字形顺序打印二叉树/把二叉树打印成多行
Q:请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推. A:BFS,偶数层reverse vector&l ...
- [TJOI2017] DNA - 后缀数组,稀疏表
[TJOI2017] DNA Description 求模式串与主串的匹配次数,容错不超过三个字符. Solution 枚举每个开始位置,进行暴力匹配,直到失配次数用光或者匹配成功.考虑到容错量很小, ...
- MODBUS TCP/IP协议规范详细介绍
1.该规范的发展概况 原始版本1997年9月3日作为公共评论的草案. 再版1999年3月29日,即修订版1.0. ...