传送门:https://www.luogu.org/problemnew/show/P3387

首先呢,tarjan找一个图的强连通分量是基于对图的dfs的。这中间开了一个dfn[]代表dfs序,还有个low[]代表该节点在dfs形成的树中能到达的最近的根。然后分情况进行更新(一会儿看我代码吧)。

为了记录一个强联通分量,我们还要在开一个栈来储存当前查找的强连通分量。如果low[x] == dfn[x],那就说明这个点在dfs树种不能往上再爬了,于是就开始弹栈。

对于这道题呢,先用tarjan找出强联通分量,然后缩点建立新图。可以发现,建立的新图是一个拓扑图,所以可以拓扑排序后在图上dp,然而我这么写wa了。翻题解的时候看到了一个更简单的方法:记录每一个点的入度,对于每一个入度为0的点用spfa跑一遍最长路,然后在所有最长路中取一个max即可。

 #include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter printf("\n")
#define space printf(" ")
#define Mem(a) memset(a, 0, sizeof(a))
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-;
const int maxn = 1e5 + ;
inline ll read()
{
ll ans = ;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) {last = ch; ch = getchar();}
while(isdigit(ch))
{
ans = ans * + ch - ''; ch = getchar();
}
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < ) x = -x, putchar('-');
if(x >= ) write(x / );
putchar('' + x % );
} vector<int> v[maxn];
int n, m, a[maxn]; int dfn[maxn], low[maxn], cnt = ;
bool in[maxn];
stack<int> st;
int col[maxn], ccol = , val[maxn];
void tarjan(int now)
{
dfn[now] = low[now] = ++cnt;
st.push(now); in[now] = ;
for(int i = ; i < (int)v[now].size(); ++i)
{
if(!dfn[v[now][i]]) //这个联通块还没找完
{
tarjan(v[now][i]);
low[now] = min(low[now], low[v[now][i]]);
}
else if(in[v[now][i]]) low[now] = min(low[now], dfn[v[now][i]]); //这个点找到了他所在联通块的祖先节点
}
if(low[now] == dfn[now]) //开始找出联通块中的所有点
{
int x; ccol++; //ccol相当于染色种数,也就是有多少个连通分量
do
{
x = st.top();
in[x] = ; st.pop();
col[x] = ccol; val[ccol] += a[x]; //val[]记录新图上的点的点权
}while(x != now);
}
return;
} vector<int> v2[maxn];
bool du[maxn];
void newGraph(int now)
{
for(int i = ; i < (int)v[now].size(); ++i)
{
int x = col[now], y = col[v[now][i]];
if(x == y) continue; //别忘了两个点在一个联通块的情况
v2[x].push_back(y);
du[y] = ;
}
return;
} int ans = ; int dis[maxn];
bool vis[maxn];
void spfa(int s)
{
Mem(vis);
for(int i = ; i <= ccol; ++i) dis[i] = -INF;
queue<int> q;
q.push(s); vis[s] = ;
dis[s] = val[s];
while(!q.empty())
{
int now = q.front(); q.pop(); vis[now] = ;
for(int i = ; i < (int)v2[now].size(); ++i)
{
if(dis[now] + val[v2[now][i]] > dis[v2[now][i]])
{
dis[v2[now][i]] = dis[now] + val[v2[now][i]];
if(!vis[v2[now][i]]) {q.push(v2[now][i]); vis[v2[now][i]] = ;}
}
}
}
for(int i = ; i <= ccol; ++i) ans = max(ans, dis[i]); //更新答案
}
int main()
{
n = read(); m = read();
for(int i = ; i <= n; ++i) a[i] = read();
for(int i = ; i <= m; ++i)
{
int x = read(), y = read();
v[x].push_back(y);
}
for(int i = ; i <= n; ++i) if(!dfn[i]) tarjan(i); //有的点从一个定点出发可能走不到,就都得判断是否走过
for(int i = ; i <= n; ++i) newGraph(i); //建立新图
for(int i = ; i <= ccol; ++i) if(!du[i]) spfa(i); //对于每一个入度为0的点,跑最长路
write(ans); enter;
return ;
}

tarjan【模板】缩点的更多相关文章

  1. 图论算法-Tarjan模板 【缩点;割顶;双连通分量】

    图论算法-Tarjan模板 [缩点:割顶:双连通分量] 为小伙伴们总结的Tarjan三大算法 Tarjan缩点(求强连通分量) int n; int low[100010],dfn[100010]; ...

  2. Tarjan的缩点&&割点概述

    What is Tarjan? Tarjan,是一种用来解决图的联通性的一种有效途径,它的一般俗称叫做:缩点.我们首先来设想一下: 如果我们有一个图,其中A,B,C构成一个环,那么我们在某种条件下,如 ...

  3. POJ 2186:Popular Cows Tarjan模板题

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 25945   Accepted: 10612 De ...

  4. BZOJ1179 [Apio2009]Atm Tarjan 强连通缩点 动态规划

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1179 题意概括 有一个有向图,每一个节点有一个权值,其中有一些结束点. 现在,你要从S出发,到达任 ...

  5. BZOJ1051 [HAOI2006]受欢迎的牛 Tarjan 强连通缩点

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1051 题意概括 有n只牛,有m个羡慕关系. 羡慕关系具有传递性. 如果A羡慕B,B羡慕C,那么我们 ...

  6. UOJ #146. 【NOIP2015】信息传递 连通分量 tarjan模板题

    http://uoj.ac/problem/146 题解:强连通分量 tarjan模板题.同时试了一下codeblock #include<bits/stdc++.h> using nam ...

  7. tarjan算法+缩点--cojs 908. 校园网

    cojs 908. 校园网 ★★   输入文件:schlnet.in   输出文件:schlnet.out   简单对比时间限制:1 s   内存限制:128 MB USACO/schlnet(译 b ...

  8. 学渣乱搞系列之Tarjan模板合集

    学渣乱搞系列之Tarjan模板合集 by 狂徒归来 一.求强连通子图 #include <iostream> #include <cstdio> #include <cs ...

  9. 洛谷1726 上白泽慧音 tarjan模板

    题目描述 在幻想乡,上白泽慧音是以知识渊博闻名的老师.春雪异变导致人间之里的很多道路都被大雪堵塞,使有的学生不能顺利地到达慧音所在的村庄.因此慧音决定换一个能够聚集最多人数的村庄作为新的教学地点.人间 ...

  10. 算法问题实战策略 MEETINGROOM 附一份tarjan模板

    地址 https://algospot.com/judge/problem/read/MEETINGROOM 解答  2-sat 代码样例过了 没有ac. 我又没有正确代码对拍..... 已确认是输出 ...

随机推荐

  1. 找xpath好用的工具(Firefox插件)

    WebDriver Element Locator 安装 打开firefox浏览器,进入网址https://addons.mozilla.org/en-US/firefox/ 在搜索框里输入WebDr ...

  2. SQL Server T—SQL 基本编程

    一 定义变量 declare   @变量名   数据类型 例:declare  @a  int              -- 变量名前必须有 @ 二 赋值 set     @变量名 = 值 sele ...

  3. android 日期控件 DatePicker

    DatePicker的缺陷 提供的API太少,没办法个性化定制.比如,不能指定某部分的颜色,不能控制显示的部分等. xml中提供的属性太少,同样影响定制化. 兼容性问题太多,在4.x,5.x和6.0+ ...

  4. 积分之迷-2015决赛C语言B组第一题

    标题:积分之迷 小明开了个网上商店,卖风铃.共有3个品牌:A,B,C. 为了促销,每件商品都会返固定的积分. 小明开业第一天收到了三笔订单: 第一笔:3个A + 7个B + 1个C,共返积分:315 ...

  5. linux系统编程:进程控制(fork)

    在linux中,用fork来创建一个子进程,该函数有如下特点: 1)执行一次,返回2次,它在父进程中的返回值是子进程的 PID,在子进程中的返回值是 0.子进程想要获得父进程的 PID 需要调用 ge ...

  6. 页面中多个script块之间方法与变量共享问题

    JS是按照代码块来进行编译和执行的,代码块间相互独立,但变量和方法共享,按顺序执行. 如: <script type='text/javascript'> var m = 0,n = 1, ...

  7. 正则匹配身份证有bug你知道么?

    在开发中,我们需要验证用户的输入信息,多半采用正则验证,下面就是身份证证号的几种常用的正则表达式: var  reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x) ...

  8. windows 10安装jdk8

    1.下载jdk,选择jdk软件版本和对应windows 32/64位版本 jdk下载链接:https://www.oracle.com/technetwork/java/javase/download ...

  9. 微信小程序开发--模板(template)使用,数据加载,点击交互

    微信小程序视图层提供了 模板(template),可以在模板中定义代码片段,然后在不同的地方调用.结果在数据渲染那懵逼了.按照官网上对模板的说明和对数据的加载. 1.定义模板 使用name属性,作为模 ...

  10. Android Design Support Library(二)用NavigationView实现抽屉菜单界面

    NavigationView在MD设计中非常重要,之前Google也提出了使用DrawerLayout来实现导航抽屉.这次,在Android Design Support Library中,Googl ...