[Explanations] && [template] Luo Gu P3387 [dot] shrink --TarJan + Topsort + DP

TarJan+Topsort+DP

Portal
Why do I feel are doing TagJan recent title? ? Sure enough, I was too Tsai yet! ! !

Title Description
Given a point n and m edges directed graph, each point has a weight, a path seeking the path through the weighted sum of the point and the maximum. You just out of this requirement and weight.

Allowing multiple passes an edge or a point, however, after the repeated point, the weight is calculated only once.

Input Output Format
Input format:
The first line, n, m

Second row, n-integers, the representative point right turn

M + 2 to the third lines of two integers u, v, represents u-> v there is a directed edge

Output formats:
a total of one line, and the point of maximum weights.
| Input Sample | Sample output |
|: - |: - |
| 2 2
1 1
1 2
2 1 | 2 |

DESCRIPTION
n <= 10 ^ 4 ^, m <= 10 ^ 5 ^, 0 <= right point <= 1000

Why the solution is "Small_Point + DP "? ? ?
Because it is seeking the right point through which the maximum points, so obviously a greedy "When I entered through a strongly connected components should been to all of them points," so we put a strongly connected component as a point, DP on the new map.
How to DP ???

    for(int i=1;i<=scc;i++)f[i]=Vaule[i];
    for(int j=1;j<=scc;j++){
        int u=Top[j];
        for(int i=LA_scc[u];i;i=NT_scc[i]){
            int v=ED_scc[i];
            f[v]=max(f[v],f[u]+Vaule[v]);
        }
    }
    //scc->强连通分量的总数
    //Vaule[i]->强连通分量中的点权总和
    //Top[j]->拓扑排序后的序列

Why should we use "TopSort" before
DP ??? total is well known, has a nature of a sequence S to the topological sorting of G:
If <V ~ x ~ V ~ y ~> are two sequence S point, and <V ~ x ~ V ~ y ~> is an edge in the graph G, then V ~ x ~ S positions is constant at V ~ y ~ before
then that this question and what relationship?
Because if you are for small to large point DP to DP you will be less in some cases.
for example there is a path: u-> v-> w;
which is the correct sequence DP DP (u) >> DP (v ) >> DP (w);
but if you do not have topological sort, you can order a DP It may be: DP (v) >> DP ( w) && DP (u) , or some other cases
You should know what I mean? ? (escape...

For details, see the code:

#include<stdio.h>
#include<bits/stdc++.h>
#define H 200005 
using namespace std;
int N,M,P[H],U[H],V[H],Ans;
int LA[H],ED[H],NT[H],tot;
int dfn[H],low[H],Belong[H],mem[H],Vaule[H],scc,Vistime;
bool InStack[H];
stack<int> S;
int LA_scc[H],ED_scc[H],NT_scc[H],QAQ,In[H];
void LB(int u,int v){ED[++tot]=v;NT[tot]=LA[u];LA[u]=tot;}
void LB_scc(int u,int v){
    ED_scc[++QAQ]=v;NT_scc[QAQ]=LA_scc[u];LA_scc[u]=QAQ;In[v]++;
}
void TarJan_scc(int u){
    dfn[u]=low[u]=++Vistime;
    InStack[u]=1;S.push(u);
    for(int i=LA[u];i;i=NT[i]){
        int v=ED[i];
        if(!dfn[v]){
            TarJan_scc(v);
            low[u]=min(low[u],low[v]);
        }
        else if(dfn[v]&&InStack[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u]){
        scc++;
        int k=0,v;
        do{
            k++;
            v=S.top();S.pop();
            Belong[v]=scc;
            InStack[v]=0;
            Vaule[scc]+=P[v];
        }while(u!=v);
        mem[scc]=k;
    }
}
void Small_Point(){
    for(int i=1;i<=M;i++){
        int x=U[i],y=V[i];
        if(Belong[x]!=Belong[y])LB_scc(Belong[x],Belong[y]);
    }
}
queue<int> Q;
int Top[H],Toptot;
void Topsort(){
    for(int i=1;i<=scc;i++)if(!In[i])Q.push(i);
    while(!Q.empty()){
        int u=Q.front();Q.pop();
        Top[++Toptot]=u;
        for(int i=LA_scc[u];i;i=NT_scc[i]){
            int v=ED_scc[i];
            In[v]--;
            if(!In[v])Q.push(v);
        }
    }
}
int f[H];
int main(){
    scanf("%d%d",&N,&M);
    for(int i=1;i<=N;i++)scanf("%d",&P[i]);
    for(int i=1;i<=M;i++){
        scanf("%d%d",&U[i],&V[i]);
        LB(U[i],V[i]);
    }
    for(int i=1;i<=N;i++)if(!dfn[i])TarJan_scc(i);
    Small_Point();
    Topsort();
    for(int i=1;i<=scc;i++)f[i]=Vaule[i];
    for(int j=1;j<=scc;j++){
        int u=Top[j];
        for(int i=LA_scc[u];i;i=NT_scc[i]){
            int v=ED_scc[i];
            f[v]=max(f[v],f[u]+Vaule[v]);
        }
    }
    for(int i=1;i<=scc;i++)Ans=max(Ans,f[i]);
    printf("%d",Ans);
}

Guess you like

Origin www.cnblogs.com/go-bananas/p/11347958.html