不爽。

为什么tarjan能爆栈啊

十分显然的缩点,给缩点之后的点连上权值为后一个点集权值的有向边,然后spfa跑最长路。

注意一开始$dis_{st}$应该等于$st$这个集合的权值。

时间复杂度$O(能过)$。

非递归版的tarjan可以学习一下。

Code:

#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
using namespace std; const int N = 8e5 + ;
const int inf = 0x3f3f3f3f; int n, m, st, edNum, dfsc = , dfn[N], low[N], bel[N];
int tot = , head[N], scc = , a[N], val[N], dis[N];
int top = , sta[N], inx[N << ], iny[N << ];
bool vis[N], isEnd[N], sccEnd[N];
stack <int> S; struct Edge {
int to, nxt, val;
} e[N << ]; inline void add(int from, int to, int v = ) {
e[++tot].to = to;
e[tot].val = v;
e[tot].nxt = head[from];
head[from] = tot;
} inline void read(int &X) {
X = ;
char ch = ;
int op = ;
for(; ch > ''|| ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline int min(int x, int y) {
return x > y ? y : x;
} inline void chkMax(int &x, int y) {
if(y > x) x = y;
} /*void tarjan(int x) {
dfn[x] = low[x] = ++dfsc;
sta[++top] = x, vis[x] = 1;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(!dfn[y]) tarjan(y), low[x] = min(low[x], low[y]);
else if(vis[y]) low[x] = min(low[x], dfn[y]);
} if(low[x] == dfn[x]) {
++scc;
for(; sta[top + 1] != x; top--) {
sccEnd[scc] |= isEnd[sta[top]];
bel[sta[top]] = scc;
val[scc] += a[sta[top]];
vis[sta[top]] = 0;
}
}
} */ void tarjan(int fir) {
low[fir] = dfn[fir] = ++dfsc;
sta[++top] = fir, vis[fir] = ;
S.push(fir);
for(; !S.empty(); ) {
int x = S.top();
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(!dfn[y]) {
dfn[y] = low[y] = ++dfsc;
sta[++top] = y, vis[y] = ;
S.push(y);
break;
}
} if(x == S.top()) {
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(dfn[y] > dfn[x]) low[x] = min(low[x], low[y]);
else if(vis[y]) low[x] = min(low[x], dfn[y]);
} if(low[x] == dfn[x]) {
++scc;
for(; sta[top + ] != x; top--) {
sccEnd[scc] |= isEnd[sta[top]];
bel[sta[top]] = scc;
val[scc] += a[sta[top]];
vis[sta[top]] = ;
}
} S.pop();
}
}
} queue <int> Q;
void spfa() {
memset(dis, 0x3f, sizeof(dis)); dis[st] = -val[st];
Q.push(st); vis[st] = ;
for(; !Q.empty(); ) {
int x = Q.front(); Q.pop();
vis[x] = ;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(dis[y] > dis[x] + e[i].val) {
dis[y] = dis[x] + e[i].val;
if(!vis[y]) Q.push(y), vis[y] = ;
}
}
}
} int main() {
read(n), read(m);
for(int x, y, i = ; i <= m; i++) {
read(x), read(y);
inx[i] = x, iny[i] = y;
add(x, y);
}
for(int i = ; i <= n; i++) read(a[i]);
read(st), read(edNum);
for(int x, i = ; i <= edNum; i++) read(x), isEnd[x] = ; for(int i = ; i <= n; i++)
if(!dfn[i]) tarjan(i); /* for(int i = 1; i <= n; i++)
printf("%d ", bel[i]);
printf("\n");
for(int i = 1; i <= n; i++)
printf("%d ", val[i]);
printf("\n"); */ tot = ; memset(head, , sizeof(head));
for(int i = ; i <= m; i++) {
if(bel[inx[i]] == bel[iny[i]]) continue;
add(bel[inx[i]], bel[iny[i]], -val[bel[iny[i]]]);
} st = bel[st];
spfa(); int ans = ;
for(int i = ; i <= scc; i++)
if(sccEnd[i] && dis[i] != inf) chkMax(ans, -dis[i]);
printf("%d\n", ans);
return ;
}

Luogu 3627 [APIO2009]抢掠计划的更多相关文章

  1. 【luogu P3627 [APIO2009]抢掠计划】 题解

    题目链接:https://www.luogu.org/problemnew/show/P3627 把点权转化到边权上去. #include <stack> #include <que ...

  2. 洛谷3627 [APIO2009]抢掠计划

    题目描述 输入格式: 第一行包含两个整数 N.M.N 表示路口的个数,M 表示道路条数.接下来 M 行,每行两个整数,这两个整数都在 1 到 N 之间,第 i+1 行的两个整数表示第 i 条道路的起点 ...

  3. 题解 P3627 【[APIO2009]抢掠计划】

    咕了四个小时整整一晚上 P3627 [APIO2009] 抢掠计划(https://www.luogu.org/problemnew/show/P3627) 不难看出答案即为该有向图的最长链长度(允许 ...

  4. P3627 [APIO2009]抢掠计划

    P3627 [APIO2009]抢掠计划 Tarjan缩点+最短(最长)路 显然的缩点...... 在缩点时,顺便维护每个强连通分量的总权值 缩完点按照惯例建个新图 然后跑一遍spfa最长路,枚举每个 ...

  5. APIO2009 抢掠计划 Tarjan DAG-DP

    APIO2009 抢掠计划 Tarjan spfa/DAG-DP 题面 一道\(Tarjan\)缩点水题.因为可以反复经过节点,所以把一个联通快中的所有路口看做一个整体,缩点后直接跑\(spfa\)或 ...

  6. [APIO2009]抢掠计划(Tarjan,SPFA)

    [APIO2009]抢掠计划 题目描述 Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruseri 银行的 ATM 取款机.令人奇怪的是, ...

  7. 【洛谷P3627】[APIO2009]抢掠计划

    抢掠计划 题目链接 比较水的缩点模板题,Tarjan缩点,重新建图,记录联通块的钱数.是否有酒吧 DAG上记忆化搜索即可 #include<iostream> #include<cs ...

  8. 洛谷 P3627 [APIO2009]抢掠计划 Tarjan缩点+Spfa求最长路

    题目地址:https://www.luogu.com.cn/problem/P3627 第一次寒假训练的结测题,思路本身不难,但对于我这个码力蒟蒻来说实现难度不小-考试时肛了将近两个半小时才刚肛出来. ...

  9. [APIO2009]抢掠计划

    题面: Description Siruseri城中的道路都是单向的.不同的道路由路口连接.按照法律的规定,在每个路口都设立了一个Siruseri银行的ATM取款机.令人奇怪的是,Siruseri的酒 ...

随机推荐

  1. New Concept English three (50)

    31 39 The New Year is a time for resolutions. Mentally, at least, most of us could compile formidabl ...

  2. 重构代码 —— 函数即变量(Replace temp with Query)

    函数即变量,这里的函数指的是返回值为某一对象的函数.Replace temp with query,query 是一种查询函数. example 1 double price() { return t ...

  3. HDU2065"红色病毒"问题【指数型母函数】

    Problem Description 医学界发现的新病毒因其蔓延速度和Internet上传播的"红色病毒"不相上下,被称为"红色病毒",经研究发现,该病毒及其 ...

  4. asp.net core mcroservices 架构之 分布式日志(二)之自定义日志开发

    netcore日志原理 netcore的日志是作为一个扩展库存在的,每个组件都有它的入口,那么作为研究这个组件的入口是最好的,首先看两种方式: 这个是源码例子提供的. var loggingConfi ...

  5. Redis底层探秘(二):链表和跳跃表

    链表简介 链表提供了高效的节点重排能力,以及顺序性的节点访问方式,并且可以通过增删节点来灵活地跳转链表的长度. 作为一种常用数据结构,链表内置在很多高级的编程语言里面,因为Redis使用C语言并没有内 ...

  6. LeetCode Reverse String II

    原题链接在这里:https://leetcode.com/problems/reverse-string-ii/#/description 题目: Given a string and an inte ...

  7. 2017.10.7北京清北综合强化班DAY7

    1.计数 (count.cpp/c/pas) 时间限制:1s 内存限制:256MB [问题描述] 给出m个数a[1],a[2],…,a[m] 求1~n中有多少数不是a[1],a[2],…,a[m]的倍 ...

  8. nodejs 安装 cnpm 命令

    npm install -g cnpm --registry=https://registry.npm.taobao.org

  9. 流畅的python之序列

    python对开发者友好的根源在于:1.序列的泛型操作2.内置的元组和映身类型3.用缩进来架构的源码4.无需变量声明的强类型 序列数据共用的一套丰富的操作:迭代.切片.排序和拼接.内置序列类型:1.容 ...

  10. git ssh登录

    .ssh下创建config文件 其内容: Host ipIdentityFile ~/.ssh/私钥文件名Port 22User git服务器的账号,不是git账号名(私钥文件名才是git账号名) 注 ...