LDUOJ- 1.27 -F. Film Club (tarjan shrink point/dp/DAG)

Title description:

The first line is a positive integer N.
The second line has N non-negative integers A[i], which represent the orzFang value of each division.
The third line has N positive integers F[i], which means that the branch reached through the wormhole of the i-th branch is F[i], and F[i]=i may occur.

Find:
Starting from the i-th branch, what is the maximum value of the sum of orzFang values.

Question idea:

For each point, there is a target point, so it is a ring-shaped directed graph.
You can shrink the point first

void tarjan(int u) {
    
    
	low[u] = dfn[u] = ++indexx;
	vis[u] =1,sta[++top] = u;
	for(int i=head[u]; ~i; i=e[i].next) {
    
    
		int v = e[i].v;
		if(!dfn[v]) tarjan(v),low[u] = min(low[u],low[v]);
		else  if(vis[v]) low[u] = min(low[u],low[v]);
	}
	if(low[u]==dfn[u]) {
    
    
		int yy;
		num++;
		do {
    
    
			yy = sta[top],id[yy] = num,nval[num]+=val[yy],top--,vis[yy] =0 ;
		} while(yy!=u);
	}
}

In this way, this graph becomes a directed acyclic graph.
The following is the dp on the DAG that you like to see.
Because starting from a point and arriving at a point-this must form a chain
. The solution to each point on the chain can be Use prefix and solve,
so the new picture after shrinking points should be reversed

void DP_ON_DAG() {
    
    
	queue<int>q;
	for(int i=1 ; i<=num; i++) 	if(deg[i]==0) q.push(i),dp[i]  =nval[i];
	while(q.size()) {
    
    
		int u = q.front();
		q.pop();
		int val = nval[u];
		for(int i=head[u]; ~i; i=e[i].next) {
    
    
			int  v= e[i].v;
			deg[v]--;
			dp[v] = dp[u]+nval[v];
			if(deg[v]==0) {
    
    
				q.push(v);
			}
		}
	}
}

Of course, it is not necessary to construct the map in reverse, just run a dfs

int  dfs(int u) {
    
    
	if(dp[u]) return dp[u];
	dp[u] = nval[u];
	for(int i = head[u]; ~i; i=e[i].next) {
    
    
		int v = e[i].v;
		dp[u]+=dfs(v);
	}
	return dp[u];
}

Guess you like

Origin blog.csdn.net/wmy0536/article/details/113261771