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 本来不想做这个题,下午总结的时候发现自己花了一周的时间学连通图却连什么是边双连通不清楚,于是百度了一下相关内容,原来就是一个点到另一个至少有两条不同的路. 题意:给 ...
随机推荐
- .NET创建一个即是可执行程序又是Windows服务的程序
不得不说,.NET中安装服务很麻烦,即要创建Service,又要创建ServiceInstall,最后还要弄一堆命令来安装和卸载. 今天给大家提供一种方式,直接使用我们的程序来安装/卸载服务,并且可以 ...
- ubuntu 18.04下安装Java
参照以下链接,这个是我找到的最易上手的学习教程了 https://blog.csdn.net/sangewuxie/article/details/80958611 按其步骤,我下载的是Java 11 ...
- 处理jquery的ajax请求session过期跳转到登录页面
首先需要在拦截器中判断是否是ajax请求,如果是 if(isAjaxRequest(request)){//ajax请求 response.setHeader("sessionstatus& ...
- Oracle笔记 #01# 简单分页
rownum是Oracle为查询结果分配的有序编号(总是从1~n).言下之意,rownum字段本来并不存在于表中,而是经查询后才分配的. 举一个例子: SELECT rownum, name, pri ...
- 【题解】Luogu P4979 矿洞:坍塌
原题传送门:P4979 矿洞:坍塌 这是某场膜你赛的题,最后我一百零几分rank三十几滚粗 这是我唯一ac的一题 这题比较简单qaq 前置芝士:珂朵莉树 窝博客里对珂朵莉树的介绍 没什么好说的自己看看 ...
- String类的知识点(不断更新)
知识点1.String类位于java.lang包中,具有丰富的方法计算字符串的长度.比较字符串.连接字符串.提取字符串2.数组的length是属性,字符串的length()是方法3.import ja ...
- oracle RAC如何正确地删除ASM磁盘组
1.登录到命令行 切换到grid用户 [grid@swnode1 ~]$ sqlplus / as sysasm SQL*Plus: Release Production on Wed May :: ...
- ldap集成grafana
grafana版本: 5.0.3 grafana通过k8s方式安装,所以需将配置文件挂载过去. cat grafana-configmap.yaml apiVersion: v1 kind: Conf ...
- 安装旧版本的Firefox
在Ubuntu上安装就版本的Firefox,此处以version 46为例子: 1.删除已存在的Firefox, On CentOS/RHEL # yum remove firefox On Ubun ...
- 数组中的元素 增加push用法 unshift() 方法 和减少pop() 方法 shift() 和其他位置增删 splice() 方法 join() 方法 reverse() 方法 sort() 方法
push用法 push 英 [pʊʃ] 美 [pʊʃ] vt. 推,推动; vt. 按; 推动,增加; 对…施加压力,逼迫; 说服; n. 推,决心; 大规模攻势; 矢志的追求 定义和用法 push( ...