tarjan 缩点(模板)
描述:
给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。
注:允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。
思路:
tarjan 的模板之一——缩点。先利用 tarjan 出图中的强连通分量及大小(点的权值),然后遍历所有点,重新构图(←重点),根据 topo DP一下,就可得出图中最大的权值和。
标程:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdlib>
#include<stack>
#include<vector>
#include<queue>
#include<deque>
#include<map>
#include<set>
using namespace std;
#define maxn 1000005
int n,m,cnt1,num,top,cnt2;//cnt1 作原图的前向星,cnt2 作新图的
int ins[maxn],head[maxn],nu[maxn],dfn[maxn],low[maxn];//nu 用来去除重边(重构图用),ins 记录强连通分量的大小
int st[maxn],co[maxn];//栈只为了表示此时是否有父子关系,co判断该点是否在栈中
int h[maxn],in[maxn],dis[maxn];//h相当于新图前向星的head,in统计点的入度,dis记录权值和(in,dis都做topo排序用)
int ans=;//统计答案
struct hh
{
int to,next,from;//from,to有可以分别记录边的起点和终点
}t1[maxn],t2[maxn];//t1原图,t2新图
inline int read()
{
int kr=,xs=;
char ls;
ls=getchar();
while(!isdigit(ls))
{
if(!(ls^))
kr=-;
ls=getchar();
}
while(isdigit(ls))
{
xs=(xs<<)+(xs<<)+(ls^);
ls=getchar();
}
return xs*kr;
}
inline void add(int x,int y)
{
t1[++cnt1].next=head[x];
t1[cnt1].from=x;
t1[cnt1].to=y;
head[x]=cnt1;
}//存原图
inline void tarjan(int x)
{
low[x]=dfn[x]=++num;
st[++top]=x;co[x]=;
for (int i=head[x];i;i=t1[i].next)
{
int v=t1[i].to;
if(!dfn[v])
{
tarjan(v);
low[x]=min(low[x],low[v]);
}
else if(co[v])
{
low[x]=min(low[x],low[v]);
}
}
if (dfn[x]==low[x])
{
int y;
while(y=st[top])
{
nu[y]=x;//表示:可以从x直接到达y(单向)
co[y]=;//y出栈(记录清除)
if(x==y) break;
ins[x]+=ins[y];//合并两个强连通分量
--top;
}
--top;
}
}//日常操作
inline void topo()
{
queue <int> q;
int tot=;
for (int i=;i<=n;i++)
if (nu[i]==i&&!in[i])//该点自己到达自己,且入度为0,表示为一个被缩为一点的强连通分量(且为起始点)
{
q.push(i);
dis[i]=ins[i];
}
while (!q.empty())//依次取出所有的起点(入度为0的点)
{
int k=q.front();q.pop();
for (int i=h[k];i;i=t2[i].next)//遍历可以到达的点
{
int v=t2[i].to;
dis[v]=max(dis[v],dis[k]+ins[v]);//更新答案
in[v]--;//入度--
if(in[v]==) q.push(v);//减到这个点入度为0,扔进队列,下次再取出作为起点
}
}
for (int i=;i<=n;i++)
ans=max(ans,dis[i]);//更新最终答案
}
int main()
{
n=read();m=read();
for (int i=;i<=n;i++)
ins[i]=read();//初始每个点认为是一个强连通分量(假装是)
for (int i=;i<=m;i++)
{
int u,v;
u=read();v=read();
add(u,v);
}
for (int i=;i<=n;i++)
if(!dfn[i])
tarjan(i);
for (int i=;i<=m;i++)
{
int x=nu[t1[i].from],y=nu[t1[i].to];
if (x!=y)//←可以去除重边
{
t2[++cnt2].next=h[x];
t2[cnt2].to=y;
t2[cnt2].from=x;
h[x]=cnt2;//重构新图
in[y]++;
}
}
topo();//topo 排序
printf("%d",ans);//输出
return ;
}
tarjan 缩点(模板)的更多相关文章
- LuoGu-P2863牛的舞会The Cow Prom[tarjan 缩点模板]
传送门:https://www.luogu.org/problemnew/show/P2863 思路:tarjan模板题,之前会的tarjan,一直想学缩点到底是什么操作,发现就是把同组的放在一个数组 ...
- 【洛谷P5008 逛庭院】tarjan缩点+贪心
既然没有题解,那么我就来提供给一份. -- 首先我们看到数据范围.妈耶!数据这么大,一开始还想用个DP来做,但是看着就不行,那么根据这个数据范围,我们大致可以猜到这道题的算法是一个贪心,那么我们怎么贪 ...
- [模板]tarjan缩点+拓扑排序
题目:给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次. 题目简述:先t ...
- 洛谷 P2194 HXY烧情侣【Tarjan缩点】 分析+题解代码
洛谷 P2194 HXY烧情侣[Tarjan缩点] 分析+题解代码 题目描述: 众所周知,HXY已经加入了FFF团.现在她要开始喜(sang)闻(xin)乐(bing)见(kuang)地烧情侣了.这里 ...
- BZOJ2199[Usaco2011 Jan]奶牛议会——2-SAT+tarjan缩点
题目描述 由于对Farmer John的领导感到极其不悦,奶牛们退出了农场,组建了奶牛议会.议会以“每头牛 都可以获得自己想要的”为原则,建立了下面的投票系统: M只到场的奶牛 (1 <= M ...
- Tarjan&&缩点简析
由于昨天写计蒜客初赛的一道题,看出了是缩点,但一时忘记了另外一个叫什么s...的算法怎么写了,话说我为什么没有回去翻一下自己的blog然后今天就去学了更实用也更强力的Tarjan Tarjan的思想其 ...
- POJ 1236 Network of Schools Tarjan缩点
Network of Schools Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 22729 Accepted: 89 ...
- HDU1269(有向图缩点模板题)
迷宫城堡 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- 初涉tarjan缩点
tarjan缩点:口胡过好多题,不过从来没写过…… 什么是缩点 tarjan和Kosaraju.Gabow算法一样,是为了求有向图中的强连通分量.因为有向图中大多数情况下会有环存在,而有环是一个不甚好 ...
- POJ-3352 Road Construction,tarjan缩点求边双连通!
Road Construction 本来不想做这个题,下午总结的时候发现自己花了一周的时间学连通图却连什么是边双连通不清楚,于是百度了一下相关内容,原来就是一个点到另一个至少有两条不同的路. 题意:给 ...
随机推荐
- How to solve the problem that BMW Icom A2 A3 host can’t be connected?
Aftre the BMW ICOM host is connected to the car via a 16PIN connector, and the other side is connect ...
- 前端框架VUE----面向对象
JavaScript 语言中,生成实例对象的传统方法是通过构造函数. function Animal(name,age){ this.name = name; this.age = age; } An ...
- struts2 的入门案例
下面写一个struts2 的一个小例子 首先需要struts2 的jar 可以在Struts 官网上下载 本人使用的版本是2.5 17 官网地址: http://struts.apache ...
- Java 安全套接字编程以及keytool 使用最佳实践
概述 利用 Java 的 JSSE(Java Secure Socket Extension)技术,我们可以方便的编写安全套接字程序,关于 JSSE 的介绍,可以参阅 Oracle 网站提供的 JSS ...
- Spring/SpringMVC/MyBatis(持久层、业务层、控制层思路小结)
准备工作: ## 7 导入省市区数据到数据库中 1. 从FTP下载SQL脚本文件 2. 把脚本文件移动到易于描述绝对路径的位置 3. 进入MySQL控制台 4. 使用`xxx_xxx`数据库 5. 运 ...
- Python cv2 OpenCV 中传统图片格式与 base64 转换
Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,是一种基于64个可打印字符来表示二进制数据的方法.通过http传输图片常常将图片数据转换成base64之后再进行传输. Base64简 ...
- php 网站中文简体繁体转换类
php 网站中文简体繁体转换类 <?php /* * define zh convert functions * 2017-4-28 use str_replace for speed * zh ...
- PHP API接口签名验证
hash_hmac 在php中hash_hmac函数就能将HMAC和一部分哈希加密算法相结合起来实现HMAC-SHA1 HMAC-SHA256 HMAC-MD5等等算法.函数介绍如下: string ...
- Shell批量启动、关闭tomcat
批量启动tomcat脚本,配置NUM可控制启动数量 #!/bin/bash #identifier CLUSTER_HOME=/opt/cluster-tomcat TNAME=tomcat-- TP ...
- android学习:apiDemos导入时R.java无法生成的问题
准备导入apiDemos研究一下别人的代码,发现导入后不能正常build,无法生成R.java,发现res/layout/progressbar_2.xml里有几个 <ProgressBar a ...