題目背景
縮點+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...