P1073 最优贸易 详细过程

怎么想

模拟样例数据之后猜想:从1开始走,记着最低价格,往后一直走,不断更新差价。

但这样碰到环就麻烦了。

所以考虑缩点,DAG图能省去一些麻烦。

阿龙要低价买入,高价卖出,而每条路可以反复地走,

那么在一个强连通分量中,阿龙一定可以在该强连通分量中售价最低处买入,最高处卖出。

可以从1所在的强连通分量开始,往后走,并记录可以买到货物的最低价格,到达一个新城市群(强连通分量)

就比较当前差价是否比之前找到的差价更大。

具体怎么实现呢,

我们可以用ccnt,vheadp[ ] ,ve[ ] 这些建一个SCC图,然后在图上跑dfs

提交!

 

 

 

 


还好不是考场,还好不是MLE,TLE,之类的

下波数据看看:发现标答是2,输出了99

事情似乎明了了

需要注意的地方


答案偏大了,说明我们可能把不满足条件的城市也加进来了

为什么说是不满足条件的呢?

   “读题呀,一定要仔细。”--化学老师

题目告诉我们:阿龙虽然需要在路上赚些生活费,但他的最终目的是终点n

而输入的图中,从某些点出发是不能到达终点的

所以我们构造反图,筛选一波。

再提交

 

 NICE

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#define FOR(i,n) for(register int i=1;i<=n;i++)
using namespace std;
const int N=100005;
struct NODE{
    int v,nxt;
};
NODE e[N*9],ve[N*9],ne[N*9];
int head[N],vhead[N],pmin[N],pmax[N],cmin[N],cmax[N],color[N],dfn[N],ins[N],low[N];
int nhead[N],ntot;
bool nvis[N];
int n,m,colorcnt,tot,vtot,timing,ans;
stack <int> s;
void add(int u,int v)
{e[++tot].v=v;e[tot].nxt=head[u];head[u]=tot;}
void vadd(int u,int v)
{ve[++vtot].v=v;ve[vtot].nxt=vhead[u];vhead[u]=vtot;}
void nadd(int u,int v){ne[++ntot].v=v;ne[ntot].nxt=nhead[u];nhead[u]=ntot;}
void tarjan(int u)
{
    ins[u]=1;
    dfn[u]=low[u]=++timing;
    s.push(u);
    for(int i=head[u];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if(!dfn[v])
        {
            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])
    {    
        colorcnt++;
        cmin[colorcnt]=1e8;
        int tmp=s.top();
        while(tmp!=u)
        {
            cmin[colorcnt]=min(cmin[colorcnt],pmin[tmp]);
            cmax[colorcnt]=max(cmax[colorcnt],pmax[tmp]);
            s.pop();
            ins[tmp]=0;
            color[tmp]=colorcnt;
            tmp=s.top();
            
        }
        ins[u]=0;color[u]=colorcnt;s.pop();
        cmin[colorcnt]=min(cmin[colorcnt],pmin[u]);
        cmax[colorcnt]=max(cmax[colorcnt],pmax[u]);
    }
}
void dfs2(int nt)
{
    if(nvis[nt]) return;
    nvis[nt]=1;
    for(int i=nhead[nt];i;i=ne[i].nxt)
        dfs2(ne[i].v);
}
void get_ans(int ccnt,int mini)
{
    if(ins[ccnt]||!nvis[ccnt]) return;
    ins[ccnt]=1;
    ans=max(ans,cmax[ccnt]-mini);
    for(int i=vhead[ccnt];i;i=ve[i].nxt)
    {
        int v=ve[i].v;
        get_ans(v,min(mini,cmin[v]));
    }
}
int main()
{ 
    //freopen("in.in","r",stdin);
    //freopen("out.out","w",stdout);
    scanf("%d%d",&n,&m);
    int a,b,c;
    FOR(i,n) cin>>pmin[i],pmax[i]=pmin[i];
    FOR(i,m)
    {
        cin>>a>>b>>c;
        add(a,b);
        if(c==2) add(b,a);
    }
    FOR(i,n)
    if(!dfn[i])
    tarjan(i);
    FOR(i,n)   
    {
        for(int j=head[i];j;j=e[j].nxt)
        {
            int v=e[j].v;
            if(color[v]!=color[i])
            {
                vadd(color[i],color[v]);
                nadd(color[v],color[i]);
            }
        }
    }
    dfs2(color[n]);
    get_ans(color[1],cmin[color[1]]);
    cout<<ans<<endl;
    return 0;
}

 

 

 

posted @ 2019-11-13 21:51  Neptune0  阅读(88)  评论(0编辑  收藏  举报