强连通分量
缩点
拓扑排序
DAG dp
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>
#include <stack>
using namespace std;
const int MAXN = 10001;
vector<int> Edge[MAXN];
vector<int> NewEdge[MAXN];
int PreWeight[MAXN] = {0};
int NewWeight[MAXN] = {0};
int DP[MAXN];
int DFN[MAXN];
int Low[MAXN];
bool Vis[MAXN];
int Belong[MAXN];
stack<int> Stack;
int idx = 0;
int Color = 0;
int N,M;
void AddEdge(int u,int v)
{
Edge[u].push_back(v);
}
void AddNewEdge(int u,int v)
{
NewEdge[u].push_back(v);
}
void Tarjan(int u)
{
DFN[u] = Low[u] = ++idx;
Stack.push(u);
Vis[u] = true;
int size = Edge[u].size();
for(int i = 0;i < size;i++)
{
int v = Edge[u][i];
if(!DFN[v])
{
Tarjan(v);
Low[u] = min(Low[u],Low[v]);
}
else if(Vis[v])
{
Low[u] = min(Low[u],DFN[v]);
}
}
if(DFN[u] == Low[u])
{
Color++;
int cur = -1;
while(cur != u)
{
cur = Stack.top();
Stack.pop();
Belong[cur] = Color;
Vis[cur] = 0;
//获得强联通块的权值
NewWeight[Color] += PreWeight[cur];
}
}
}
inline int Topo(void)
{
queue<int> Que;
int In[MAXN] = {0};
for(int i = 1;i <= Color;i++)
{
for(int j = 0;j < NewEdge[i].size();j++)
{
int v = NewEdge[i][j];
In[v]++;
}
}
for(int i = 1;i <= Color;i++)
{
if(In[i] == 0)
{
Que.push(i);
//DP初始值
DP[i] = NewWeight[i];
}
}
int ans = 0;
while(Que.size())
{
int v = Que.front();
Que.pop();
for(int i = 0;i < NewEdge[v].size();i++)
{
int Now = NewEdge[v][i];
DP[Now] = max(DP[Now],DP[v]+NewWeight[Now]);
In[Now]--;
if(In[Now] == 0)
{
Que.push(Now);
}
}
}
for(int i = 1;i <= Color;i++)
{
ans = max(ans,DP[i]);
}
return ans;
}
int main(void)
{
cin >> N >> M;
for(int i = 1;i <= N;i++)
{
cin >> PreWeight[i];
}
for(int i = 1;i <= M;i++)
{
int u,v;
cin >> u >> v;
AddEdge(u,v);
}
for(int i = 1;i <= N;i++)
{
if(!DFN[i])
{
Tarjan(i);
}
}
for(int u = 1;u <= N;u++)
{
int size = Edge[u].size();
for(int j = 0;j < size;j++)
{
int v = Edge[u][j];
if(Belong[u] != Belong[v])
{
AddNewEdge(Belong[u],Belong[v]);
}
}
}
int res = 0;
res = Topo();
cout << res << endl;
return 0;
}