标签:close pac tin val pop read struct 复杂度 head
不爽。
为什么tarjan能爆栈啊
十分显然的缩点,给缩点之后的点连上权值为后一个点集权值的有向边,然后spfa跑最长路。
注意一开始$dis_{st}$应该等于$st$这个集合的权值。
时间复杂度$O(能过)$。
非递归版的tarjan可以学习一下。
Code:
#include
#include
#include
#include using namespace std;
const int N = 8e5 + 5;
const int inf = 0x3f3f3f3f;
int n, m, st, edNum, dfsc = 0, dfn[N], low[N], bel[N];
int tot = 0, head[N], scc = 0, a[N], val[N], dis[N];
int top = 0, sta[N], inx[N 1], iny[N 1];
bool vis[N], isEnd[N], sccEnd[N];
stack int> S;
struct Edge {
int to, nxt, val;
} e[N 1];
inline void add(int from, int to, int v = 0) {
e[++tot].to = to;
e[tot].val = v;
e[tot].nxt = head[from];
head[from] = tot;
}
inline void read(int &X) {
X = 0;
char ch = 0;
int op = 1;
for(; ch > ‘9‘|| ch ‘0‘; ch = getchar())
if(ch == ‘-‘) op = -1;
for(; ch >= ‘0‘ && ch ‘9‘; ch = getchar())
X = (X 3) + (X 1) + ch - 48;
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] = 1;
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] = 1;
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 + 1] != x; top--) {
sccEnd[scc] |= isEnd[sta[top]];
bel[sta[top]] = scc;
val[scc] += a[sta[top]];
vis[sta[top]] = 0;
}
}
S.pop();
}
}
}
queue int> Q;
void spfa() {
memset(dis, 0x3f, sizeof(dis)); dis[st] = -val[st];
Q.push(st); vis[st] = 1;
for(; !Q.empty(); ) {
int x = Q.front(); Q.pop();
vis[x] = 0;
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] = 1;
}
}
}
}
int main() {
read(n), read(m);
for(int x, y, i = 1; i ) {
read(x), read(y);
inx[i] = x, iny[i] = y;
add(x, y);
}
for(int i = 1; i ) read(a[i]);
read(st), read(edNum);
for(int x, i = 1; i 1;
for(int i = 1; i )
if(!dfn[i]) tarjan(i);
/* for(int i = 1; i */
tot = 0; memset(head, 0, sizeof(head));
for(int i = 1; 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 = 0;
for(int i = 1; i )
if(sccEnd[i] && dis[i] != inf) chkMax(ans, -dis[i]);
printf("%d\n", ans);
return 0;
}
View Code
Luogu 3627 [APIO2009]抢掠计划
标签:close pac tin val pop read struct 复杂度 head
原文地址:https://www.cnblogs.com/CzxingcHen/p/9529574.html