Luogu P1073最適な取引-(tarjanシュリンクポイント+ DAG + dp +トポロジカルソート)

この問題には10,000の解決策があるようです。spfa、階層マップ転送、およびbfsの双方向拡張があります。

タイトル説明:

n個のポイントとm個のエッジがあります。各ポイントには、この時点での水晶玉の売買の価格を表す重みがあります。
人は1からnまで歩き、あなたが最大にできる違いは何ですか(売買のみ)と尋ねます。一度)

質問のアイデア:

これはリング付きの有向グラフです。
まず、リングをポイントに縮小し、この時点での売買の最高価格と最低価格を記録します
(リング内のすべてのポイントについて、これらのポイントが互いに到達できるため) )、
グラフが変化し
、現在の点uを満たすDAGになります。

dp[u] = max(max(dp[u],dp[v]),val_max[u]-minn[v]);

その中で、max(dp[u],dp[v])nポイントに到達できるパスの最大差を記録します

最初はdp [v] = val_max [v] -minn [v]にプッシュさ
れ、次に片側をスイープして最大値を取得しました。
最後に到達したポイントがポイントnではない可能性があります。

コード:

int head[maxn],cnt,n,m,val[maxn],vis[maxn],dfn[maxn],low[maxn],indexx,minn[maxn];
int block,id[maxn],cnt1,head1[maxn],in[maxn],valma[maxn],valmi[maxn],dp[maxn];
stack<int>st;
struct node {
    
    
    int u,v,next;
} e[maxn],zan[maxn];
void add1(int u,int v ) {
    
    
    zan[cnt1].u=u;
    zan[cnt1].v=v;
    zan[cnt1].next=head1[u];
    head1[u]=cnt1++;
}
void add(int u,int v ) {
    
    
    e[cnt].u=u;
    e[cnt].v=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}
void tarjan(int u) {
    
    
    dfn[u] = low[u] = ++indexx;
    vis[u] = 1;
    st.push(u);
    for(int i=head1[u]; ~i; i=zan[i].next) {
    
    
        int v  = zan[i].v;
        if(dfn[v]==0) tarjan(v),  low [u] = min(low[u],low[v]);
        else if(vis[v])    low[u] = min(low[u],dfn[v]);
    }
    int ma = -inf,mi = inf;
    if(low[u] == dfn[u]) {
    
    
        int yy;
        block++;
        do {
    
    
            yy = st.top();
            st.pop();
            vis[yy] =0 ;
            ma =max(ma,val[yy]);
            mi =min(mi,val[yy]);
            id[yy]  = block;
        } while(yy!=u);
        valmi[block] = mi;
        valma[block] = ma;
    }
}
void top_sort() {
    
    
    queue<int>q;

    q.push(id[1]);

    while(q.size()) {
    
    
        int u = q.front();
        q.pop();
        for(int i =head[u]; ~i; i=e[i].next) {
    
    
            int v = e[i].v;
            minn[v] = min (minn[u],valmi[v]);
            dp[v] = max(max(dp[u],dp[v]),valma[v]-minn[v]);
            in[v]--;
            if(in[v]==0) q.push(v);
        }
    }
}
int main() {
    
    
    mst(head1,-1);
    n=read(),m=read(),mst(head,-1);
    rep(i,1,n) val[i] = read(),minn[i] = inf;
    for(int i=1 ; i<=m ; i++) {
    
    
        int op,u,v;
        u=read(),v=read(),op=read();
        add1(u,v);
        if(op==2) add1(v,u);
    }
    tarjan(1);
    for(int i = 0 ; i<cnt1 ; i++) {
    
    
        int u = zan[i].u;
        int v = zan[i].v;
        if(id[u]!=id[v]) add(id[u],id[v]),in[id[v]]++;
    }
    top_sort();
    out(dp[id[n]]);
    return 0;
}

おすすめ

転載: blog.csdn.net/wmy0536/article/details/110527771