Luogu3387【模板】缩点(Kosaraju)
原题链接:https://www.luogu.org/problemnew/show/P3387
【模板】缩点
题目背景
缩点+DP
题目描述
给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。
允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。
输入输出格式
输入格式:
第一行,n,m
第二行,n个整数,依次代表点权
第三至m+2行,每行两个整数u,v,表示u->v有一条有向边
输出格式:
共一行,最大的点权之和。
输入输出样例
输入样例#1:
2 2
1 1
1 2
2 1
输出样例#1:
2
说明
n<=104,m<=105n<=10^4,m<=10^5n<=104,m<=105,点权<=1000
算法:Tarjan缩点+DAGdp
题解
学习一下求scc\mathcal{scc}scc的新姿势Kosaraju\mathcal{Kosaraju}Kosaraju。
算法流程:
1.在反向图上dfsdfsdfs,返回时将当前点放进栈里。
2.从栈尾倒序dfsdfsdfs,每次dfsdfsdfs到的点都在一个sccsccscc里。
先考虑下面这个简单有向图:
如果我们从B\mathcal{B}B部分开始dfsdfsdfs,那么每次出来的都是一个sccsccscc,但是从A\mathcal{A}A开始就会把整张图误判为一个sccsccscc。
如果我们要让每次dfsdfsdfs到的恰好构成一个sccsccscc,就要使这个sccsccscc内的点没有指向其他未被遍历过的sccsccscc,如564132564132564132这个顺序。
但这个条件似乎太过苛刻了,只要有一个B\mathcal{B}B部分的点排在了第一个,我们就能得到正确的答案,所以我们需要第一次dfsdfsdfs来搞出反向图的伪拓扑序,按照这个伪拓扑序dfsdfsdfs就能得到正确的答案辣!
代码
#include<bits/stdc++.h>
using namespace std;
const int M=2e5+5,N=1e4+5;
int val[N],head[M],nxt[M],to[M],sta[N],col[N],dp[N],top,tot,cnt,n,m;
bool vis[N];
vector<int>mmp[M],scc[M];
void add(int f,int t){nxt[++cnt]=head[f],head[f]=cnt,to[cnt]=t;}
void dfs1(int v){int i;for(vis[v]=1,i=head[v];i;i=nxt[i])if(!vis[to[i]])dfs1(to[i]);sta[++top]=v;}
void dfs2(int v){int i;for(vis[v]=1,scc[tot].push_back(v),col[v]=tot,dp[tot]+=val[v],i=mmp[v].size()-1;i>=0;--i)if(!vis[mmp[v][i]])dfs2(mmp[v][i]);}
void dfs3(int v)
{if(vis[v])return;vis[v]=1;int i,j,mx=0,t;for(i=scc[v].size()-1;i>=0;--i)for(j=mmp[scc[v][i]].size()-1;j>=0;--j){t=col[mmp[scc[v][i]][j]];if(t==v)continue;if(!vis[t])dfs3(t);mx=max(mx,dp[t]);}dp[v]+=mx;
}
void in()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;++i)scanf("%d",&val[i]);for(int i=1,a,b;i<=m;++i)scanf("%d%d",&a,&b),add(b,a),mmp[a].push_back(b);
}
void ac()
{int i,mx=0;for(i=1;i<=n;++i)if(!vis[i])dfs1(i);memset(vis,0,sizeof(vis));for(i=top;i>=1;--i)if(!vis[sta[i]])++tot,dfs2(sta[i]);memset(vis,0,sizeof(vis));for(i=1;i<=tot;++i)if(!vis[i])dfs3(i);for(int i=1;i<=tot;++i)mx=max(mx,dp[i]);printf("%d",mx);
}
int main(){in();ac();}
Luogu3387【模板】缩点(Kosaraju)相关推荐
- 洛谷3387 模板 缩点
题目:缩点 思路:tarjan缩点+最长路. 注意: 1.用dijkstra求最长路时,优先队列中的<运算符要反过来. 2.需要把所有入度为0的点为起点跑一遍最长路. 3.每次求最长路时,dis ...
- Tarjan相关最全(附训练题和答案)
Tarjan相关最全(附训练题和答案) 算法思想 Tarjan 强连通分量 割点 割桥 缩点 Kosaraju Garbow 训练 POJ2186 POJ1236 POJ2375 Luogu P338 ...
- html标签属性可以省略,html部分---通用标签与属性;
body的属性: bgcolor页面背景色:text文字颜色:topmargin上页边距:leftmargin左页边距:rightmargin右页边距:bottomargin下页边距: src是引用过 ...
- 图(八):强连通分量
强连通分量 强连通分量是针对有向图来说的,当一个有向图中所有的点都能够相互到达则称这个图为强连通分量. 一.模板 int dfn[N], low[N], dfncnt, s[N], in_stack[ ...
- 图论,专为迷途少年而生
文章目录 目录 图的存储 邻接矩阵 前向星 Topsort P1038 神经网络 P1983 车站分级 最小生成树 MST 堆优化Prim 并查集Kruskal Matrix Tree Theory ...
- 解题报告:luogu P2341 受欢迎的牛(Tarjan算法,强连通分量判定,缩点,模板)
题目链接:洛谷 受欢迎的牛 基本上算是一道模板题 根据题意,如果有环,意味着这个环里的牛都互相喜欢 我们可以先求出环,然后把每一个环都看作一个点,这样整个图就变成了一个DAG(有向无环图) 看有几个点 ...
- 强连通分量:洛谷P3387 模板:缩点
传送门 顾名思义,模板awa #include <cstdio> #include <cstring> #include <cmath> #include < ...
- 浅谈Tarjan缩点(分析+模板)
昨天一看发现我的博客数量到100篇了,撒花✿✿ヽ(°▽°)ノ✿ 根据标题我们也知道,想要在接下来的十分钟不浪费生命 读者需要先行学习Tarjan强联通分量 如果不会的话可以点击这里:https://w ...
- 图论--有向图强连通分量的标记及缩点模板
有向图中在若两点之间可以互相到达,则称这两点强连通,如果一个点集内的所有点都可以互相到达,那么这个点集就是图的一个强连通分量,而我们需要找出有向图中的所有极大强连通分量,于是就用Tarjan算法进行强 ...
- 洛谷 P3387 【模板】缩点
题目 题目背景 缩点+DP 题目描述 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点, ...
最新文章
- Python isinstance() 函数
- 基于IMX515EVK+WINCE6.0---支持PB6.0通过USB下载镜像文件
- 【数理知识】《数值分析》李庆扬老师-第6章-解线性方程组的迭代法
- 初学者在python下使用Ta-lib库时遇到的一些问题及解决办法
- 倒排索引、分词、同义词
- 嵌入式中常见的存储器总结(一)存储器分类
- 【周记:距gdoi43天】
- 我辞掉程序员的工作,体验了半年的自驾游生活
- zabbix-自定义键值监控网卡IN、OUT流量
- 计算机windows7更新失败,win7笔记本电脑配置update失败如何解决
- 计算机网络掉线,电脑网络经常掉线的解决方法
- warmup与余弦退火学习率
- 智能车心得分享(五)-- 电磁排布
- ⊱如果事与愿违,请相信一定另有安排
- 常见英文缩写小节-江晚正愁余-iteye技术网站
- Vue 中echarts的数据参数使用、X轴Y轴
- facebook 分享页面_如何建立Facebook页面
- MOSFET是什么器件,它的作用是什么
- android之按钮添加声音
- Apache Atlas 安装部署