Luogu3387 模板 縮點(Kosaraju)

2021-08-28 14:15:32 字數 1977 閱讀 4256

題目背景

縮點+dp

題目描述

給定乙個n個點m條邊有向圖,每個點有乙個權值,求一條路徑,使路徑經過的點權值之和最大。你只需要求出這個權值和。

允許多次經過一條邊或者乙個點,但是,重複經過的點,權值只計算一次。

輸入輸出格式

輸入格式:

第一行,n,m

第二行,n個整數,依次代表點權

第三至m+2行,每行兩個整數u,v,表示u->v有一條有向邊

輸出格式:

共一行,最大的點權之和。

輸入輸出樣例

輸入樣例#1:

2 21 1

1 22 1

輸出樣例#1:說明n

<=1

04,m

<=1

05n<=10^4,m<=10^5

n<=1

04,m

<=1

05,點權<=1000

演算法:tarjan縮點+dagdp

題解學習一下求scc

\mathcal

scc的新姿勢kos

araj

u\mathcal

kosara

ju。演算法流程:

1.在反向圖上dfs

dfsdf

s,返回時將當前點放進棧裡。

2.從棧尾倒序dfs

dfsdf

s,每次dfs

dfsdf

s到的點都在乙個scc

sccsc

c裡。先考慮下面這個簡單有向圖:

如果我們從b

\mathcal

b部分開始dfs

dfsdf

s,那麼每次出來的都是乙個scc

sccsc

c,但是從a

\mathcal

a開始就會把整張圖誤判為乙個scc

sccsc

c。如果我們要讓每次dfs

dfsdf

s到的恰好構成乙個scc

sccsc

c,就要使這個scc

sccsc

c內的點沒有指向其他未被遍歷過的scc

sccsc

c,如564132

564132

564132

這個順序。

但這個條件似乎太過苛刻了,只要有乙個b

\mathcal

b部分的點排在了第乙個,我們就能得到正確的答案,所以我們需要第一次dfs

dfsdf

s來搞出反向圖的偽拓撲序,按照這個偽拓撲序dfs

dfsdf

s就能得到正確的答案辣!

**

#include

using

namespace std;

const

int m=

2e5+

5,n=

1e4+5;

int val[n]

,head[m]

,nxt[m]

,to[m]

,sta[n]

,col[n]

,dp[n]

,top,tot,cnt,n,m;

bool vis[n]

;vector<

int>mmp[m]

,scc[m]

;void

add(

int f,

int t)

void

dfs1

(int v)

void

dfs2

(int v)

void

dfs3

(int v)

dp[v]

+=mx;

}voidin(

)voidac(

)int

main()

tarjan dp P3387 模板 縮點

可以多次走乙個點或一條邊,但只計算一次點權,意味著我們需要進行縮點 tarjan進行求強聯通分量主要記錄dfn i low i 以及維護que記錄走過的點 通過後向邊和樹枝邊對low值的更新,當dfn i low i 時,就出現了強連通分量,可以進行縮點操作 在縮點後,重新建圖,然後就可以通過dp ...

P3387 模板 縮點

r es ul tresult result h yp erli nk hyperlink hyperl ink de scri ptio ndescription descri ptio n 給定一張n nn個點,m mm條邊的有向圖,點有點權 找出一條路徑使得經過的點的權值和最大,點和邊可以重複...

Luogu P3387 模板 縮點

這個題不難,就是先trajan縮點減小點數和邊數的規模,然後在縮完點的圖上跑dp即可。注意要用toposort解決dp後效性 或者是使用記憶化搜尋 code include include include include define maxn 10010 define maxm 500100 in...