Tarjan缩点

有向图 点有权 走一条路径,上面的所有点的权值只算一次 使和最大

先tarjan把强连通分量缩点嘛
这样图就变成DAG啦,没有后效性的话dp乱搞一下就好了

#include
using namespace std;

const int MAXN=16384;
int n,m,vap[MAXN],bel[MAXN],val[MAXN];
vector gra[MAXN],neg[MAXN];

char c;
inline void read(int &x)
{
    x=0,c=getchar();
    while(c<'0' || '9' stc;
bool inst[MAXN];
int dfn[MAXN],low[MAXN],tim,cnt;
void tarjan(int nod)
{
    stc.push(nod),inst[nod]=true;
    dfn[nod]=low[nod]=++tim;
    int len=gra[nod].size(),here;
    for(int i=0;i!=len;++i)
    {
        if(!dfn[gra[nod][i]])		tarjan(gra[nod][i]),low[nod]=min(low[nod],low[gra[nod][i]]);
        else if(inst[gra[nod][i]])	low[nod]=min(low[nod],dfn[gra[nod][i]]);
    }
    if(dfn[nod]!=low[nod])	return;
    ++cnt,here=0;
    while(here!=nod)
    {
        here=stc.top(),stc.pop();
        inst[here]=false;
        bel[here]=cnt,val[cnt]+=vap[here];
    }
}

int dis[MAXN];
void dfs(int nod)
{
    if(dis[nod])	return;
    dis[nod]=val[nod];
    int len=neg[nod].size(),mos=0;
    for(int i=0;i!=len;++i)
    {
        if(!dis[nod])	dfs(neg[nod][i]);
        mos=max(mos,dis[neg[nod][i]]);
    }
    dis[nod]+=mos;
}

int main()
{
    read(n),read(m);
    for(int i=1;i<=n;read(vap[i++]));
    for(int i=0,a,b;i!=m;++i)
        read(a),read(b),gra[a].push_back(b);
    for(int i=1;i<=n;++i)
        if(!dfn[i])	tarjan(i);
    for(int i=1;i<=n;++i)
    {
        int len=gra[i].size();
        for(int j=0;j!=len;++j)
            if(bel[i]!=bel[gra[i][j]])
                neg[bel[i]].push_back(bel[gra[i][j]]);
        gra[i].clear();
    }
    int ans=-1;
    for(int i=1;i<=cnt;++i)
        dfs(i),ans=max(ans,dis[i]);
    cout<

你可能感兴趣的:(板子)