縮點+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...