模板 縮點 tarjan,DAG上DP

2022-02-27 05:19:07 字數 1717 閱讀 2283

縮點+dp

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

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

輸入格式:

第一行,n,m

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

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

輸出格式:

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

顯然,由於點權為正,所以位於乙個強連通分量中的結點,自然走得越多答案越大

所以,我們可以跑一邊tarjan,將所有的強連通分量染色,建乙個新的圖

其中新圖上的每個結點都代表舊圖上的乙個強連通分量

在跑tarjan染色的同時我們可以累加得到新圖上每個點的點權

最後在新圖上跑一邊dp或者記憶化搜尋即可

#include#include

#include

#include

#define rii register int i

#define rij register int j

using

namespace

std;

struct

yby[

100005

];struct

ljbx[

100005

];int tot,dq[10005],sta[10005],sum[10005],head[10005],bnt,last[10005

];int n,m,dfn[10005],low[10005],top,cnt,vis[10005],color[10005],dp[10005

];void add(int

from,int

to)

if(last[from]!=0

)

last[

from]=bnt;

}void search(int

wz) dp[wz]=sum[wz];

int maxn=0

;

for(rii=head[wz];i!=0;i=x[i].nxt)

maxn=max(maxn,dp[ltt]);

}dp[wz]+=maxn;

}void tarjan(int

wz)

else}}

if(dfn[wz]==low[wz])

}}int

main()

for(rii=1;i<=m;i++)

for(rii=1;i<=n;i++)

}/*for(rii=1;i<=n;i++)

cout<*/

bnt=0

; memset(head,

0,sizeof

(head));

memset(last,

0,sizeof

(last));

memset(x,

0,sizeof

(x));

for(rii=1;i<=m;i++)

}int ans=0

;

for(rii=1;i<=n;i++)

ans=max(ans,dp[i]);

}printf(

"%d\n

",ans);

}

Tarjan 縮點 模板

縮點以後,整張圖變為dag 有向無環圖 此時運用拓撲排序 求出度入度就可以完成許多事 題目 include include include include include include define ll long long using namespace std const int maxn 1...

tarjan 模板 縮點

傳送門 首先呢,tarjan找乙個圖的強連通分量是基於對圖的dfs的。這中間開了乙個dfn代表dfs序,還有個low代表該節點在dfs形成的樹中能到達的最近的根。然後分情況進行更新 一會兒看我 吧 為了記錄乙個強聯通分量,我們還要在開乙個棧來儲存當前查詢的強連通分量。如果low x dfn x 那就...

學習 模板 tarjan縮點

我美好的早上就被tarjan毀掉了 微笑 放資料qwq謝謝你們讓我學會了tarjan 前兩個還是讓我了解了tarjan而最後乙個可就厲害了還讓我鞏固了topo sort dag 上的dp!學習筆記詳見注釋quq 1 include2 include3 include4 define maxn 100...