luogu P1073] [Optimal Trade

The first chapter of konjac solution to a problem, bigwigs light spray (shivering

Closer to home, this question
see the solution to a problem area bigwigs with a wide variety of algorithms gods cut out the problem, and does not indicate a small konjac algorithm so many gods, and thus be out of the water solution to a problem to talk about their own practices.

Algorithm: Tarjan + topological sorting + DP

Ideas: see this question first thought tarjan shrink point (I will not tell you this is because I will only tarjanAfter tarjan a directed acyclic graph, naturally conceivable dp topologically sorted, then the general idea of ​​solving the problem came out.

The first step tarjan point reduction

void tarjan(int u){
    dfn[u]=low[u]=++num;
    s[++temp]=u;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!color[v]) low[u]=min(low[u],low[v]);
    }
    if(dfn[u]==low[u]){
        color[u]=++sum;
        ma[sum]=max(ma[sum],cost[u]);//维护强连通分量中最大的商品价格
        mi[sum]=min(mi[sum],cost[u]);//维护强连通分量中最小的商品价格
        while(s[temp]!=u){
            ma[sum]=max(ma[sum],cost[s[temp]]);
            mi[sum]=min(mi[sum],cost[s[temp]]);//同上
            color[s[temp--]]=sum;
        }
        --temp;
    }
}

Step topological sorting + DP

State transition equation dp's quite easy to think of it.

dp[to]=max{ma[to]-mi[k]}

To here represents the point to be found, mi [k] represents the minimum value of the entry path commodity prices

inline void tuopu(){
    queue<int> q;
    q.push(color[1]);
    ans[color[1]]=ma[color[1]]-mi[color[1]];
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=head[u];i;i=ne[i].next){
            int v=ne[i].to;
            --rd[v];
            mi[v]=min(mi[v],mi[u]);//维护路径上经过的最小值
            ans[v]=max(ans[u],ma[v]-mi[v]);//dp状态转移
            if(!rd[v]) q.push(v);
        }
    }
}

Here's the key code for this problem will be solved

The following release total code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define INF 2e9+11;
using namespace std;
const int N=100000+11;
const int M=500000+11;
int n,m,sum,num,temp,tot;
int head[N],dfn[N],low[N],s[N],color[N],ma[N],mi[N],cost[N],rd[N],ans[N];
struct Edge{
    int from,next,to;
}e[M],ne[M];
inline void read(int &a){
    a=0;
    char c=getchar();
    while(c>57 or c<48)c=getchar();
    while(47<c and c<58){
        a=a*10+c-48;
        c=getchar();
    }
}
inline int max(int x,int y){return x > y ? x : y;}
inline int min(int x,int y){return x > y ? y : x;}
inline void add_edge(int from,int to){
    e[++tot].next=head[from];
    e[tot].from=from;
    e[tot].to=to;
    head[from]=tot;
}//链式前向星建边
void tarjan(int u){
    dfn[u]=low[u]=++num;
    s[++temp]=u;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!color[v]) low[u]=min(low[u],low[v]);
    }
    if(dfn[u]==low[u]){
        color[u]=++sum;
        ma[sum]=max(ma[sum],cost[u]);
        mi[sum]=min(mi[sum],cost[u]);
        while(s[temp]!=u){
            ma[sum]=max(ma[sum],cost[s[temp]]);//维护强连通分量中最大的商品价格
            mi[sum]=min(mi[sum],cost[s[temp]]);//维护强连通分量中最小的商品价格
            color[s[temp--]]=sum;
        }
        --temp;
    }
}
inline void tuopu(){
    queue<int> q;
    q.push(color[1]);
    ans[color[1]]=ma[color[1]]-mi[color[1]];
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=head[u];i;i=ne[i].next){
            int v=ne[i].to;
            --rd[v];
            mi[v]=min(mi[v],mi[u]);//维护路径上经过的最小值
            ans[v]=max(ans[u],ma[v]-mi[v]);//dp状态转移
            if(!rd[v]) q.push(v);
        }
    }
}
int main(){
    read(n);read(m);
    for(int i=1;i<=n;++i) read(cost[i]);
    int x,y,z;
    for(int i=1;i<=m;++i){
        read(x);read(y);read(z);
        if(z&1) add_edge(x,y);
        else{
            add_edge(x,y);
            add_edge(y,x);
        }
    }
    for(int i=1;i<=n;++i) mi[i]=INF;//初始化mi数组
    for(int i=1;i<=n;++i)
        if(!dfn[i]) tarjan(i);
    tot=0;
    memset(head,0,sizeof(head));
    for(int i=1;i<=m;++i)
        if(color[e[i].from]!=color[e[i].to]){
            ++rd[color[e[i].to]];
            ne[++tot].next=head[color[e[i].from]];
            ne[tot].to=color[e[i].to];
            head[color[e[i].from]]=tot;
        }//缩点之后的新图建边
    tuopu();
    printf("%d",ans[color[n]]);
    return 0;
}

If you do not know where I can private letter, if there is an error where chiefs welcome to correct me (Welcome to beating and hanging my deities

Guess you like

Origin www.cnblogs.com/cnyali-xwx/p/11323648.html