APIO2009略奪計画Tarjan DAG-DP

APIO2009略奪計画Tarjan DAG-DP

フェイス質問

\(Tarjan \)は、少量の水問題を縮小します。それは、ノードを介して繰り返すことができるので、全体として見高速リンクの全ての接合部に、直接、またはのようなポイントDPのspfaを凝縮した後に実行します。

私は、結局、DAG上の複雑DPを実行することにしました(\ O(n))を\を

DPトポロジ、係合\を(F [I] \) DAGに示される\(Iは\)ノード、送金の現在の最大数\(F [V] =最大 (F [V]、F [U] + W [V])\)

#include <cstdio>
#include <queue>
#define MAXN 500005
#define MIN(A,B) ((A)<(B)?(A):(B))
#define MAX(A,B) ((A)>(B)?(A):(B))
using namespace std;
int n,m,sta,p;
bool hav[MAXN],col_hav[MAXN];
int head[MAXN],nxt[MAXN],vv[MAXN],tot;
inline void add_edge(int u, int v){
    vv[++tot]=v;
    nxt[tot]=head[u];
    head[u]=tot;
}
int s[MAXN],top;
bool ins[MAXN];
int col[MAXN],col_cnt;
int val[MAXN],col_val[MAXN];
int low[MAXN],dfn[MAXN],cnt;
void tarjan(int u){
    dfn[u]=++cnt;
    low[u]=cnt;
    s[++top]=u;
    ins[u]=1;
    for(register int i=head[u];i;i=nxt[i]){
        int v=vv[i];
        if(dfn[v]==0){
            tarjan(v);
            low[u]=MIN(low[u], low[v]);
        }else if(ins[v]){
            low[u]=MIN(low[u], dfn[v]);
        }
    }
    if(dfn[u]==low[u]){
        col[u]=++col_cnt;
        ins[u]=0;
        col_val[col_cnt]=val[u];
        while(s[top]!=u){
            col[s[top]]=col_cnt;
            ins[s[top]]=0;
            col_val[col_cnt]+=val[s[top]];
            top--;
        }
        top--;
    }
}
int head2[MAXN],nxt2[MAXN],vv2[MAXN],tot2;
inline void add_edge2(int u, int v){
    vv2[++tot2]=v;
    nxt2[tot2]=head2[u];
    head2[u]=tot2;
}
int rdu[MAXN];
inline void build(){
    for(register int u=1;u<=n;++u)
    if(dfn[u]!=0){
        for(register int i=head[u];i;i=nxt[i]){
            int v=vv[i];
            if(col[u]==col[v]) continue;
            rdu[col[v]]++;
            add_edge2(col[u], col[v]);
        }
    }
}
queue <int> q;
int f[MAXN],ans=0;
void dp(){
    q.push(col[sta]);f[col[sta]]=col_val[col[sta]];
    while(!q.empty()){
        int u=q.front();q.pop();
        for(register int i=head2[u];i;i=nxt2[i]){
            int v=vv2[i];
            f[v]=MAX(f[v], f[u]+col_val[v]);
            if((--rdu[v])==0) q.push(v);
        }
    }
    for(register int i=1;i<=col_cnt;++i)
        if(col_hav[i]) ans=MAX(f[i], ans);
}
int main()
{
    scanf("%d %d", &n, &m);
    while(m--){
        int a,b;scanf("%d %d", &a, &b);
        add_edge(a,b);
    }
    for(register int i=1;i<=n;++i) scanf("%d", &val[i]);
    scanf("%d %d", &sta, &p);
    while(p--){
        int x;scanf("%d", &x);
        hav[x]=1;
    }
    tarjan(sta);
    for(register int i=1;i<=n;++i)
        if(hav[i]) col_hav[col[i]]=1;
    build();
    dp();
    printf("%d", ans);
    return 0;
}

おすすめ

転載: www.cnblogs.com/santiego/p/10943425.html