codevs1173最优贸易

这应该是题目传送门的位置

相当坑爹

原本看完题解还是满怀信心的

结果写了四遍都没过

什么叫两遍spfa就行啊!!!

最后没办法看了人家的代码

自己再想想才写出来

太耻辱了

它其实是先开两个数组

一个是maxn[],一个是minn[]

 用于存到到达当前节点的最大卖出值和最小买入值

当然初始化为最小值和最大值就行

这就需要建立反向边

然后每次用类似宽搜的办法扩张出去

正向的搜minn[]

反向的搜maxn[]

先讲正向吧(反向的思路自己根据这个YY)

1.先把第一个节点更新为它自己原来的值,存入队列,标记于队列中

2.出队,标记掉,寻找这个点的出边

3.如果这个点(u点)出边的点(v点)的minn值(minn[v])大于自己的值或者是大于minn[u],就更新它,入队,并标记

如此反复即可

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int _maxn=100010;
queue<int> q;
struct e
{
    int to,Next;
}a[1000011];
bool vis[_maxn];
int head[_maxn],maxn[_maxn],minn[_maxn],headf[_maxn],a1[_maxn],n,m,k=0;
void add(int x,int y)
{
    a[++k].to=y;
    a[k].Next=head[x];
    head[x]=k;
    a[++k].to=x;
    a[k].Next=headf[y];
    headf[y]=k;
}
void read()
{
    int x,y,z,ai;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a1[i]);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y);
        if(z==2)
            add(y,x);
    }
}
void spfa1()
{
    int u,v;
    memset(vis,false,sizeof(vis));
    memset(minn,0x7f,sizeof(minn)); 
    q.push(1);
    vis[1]=true;
    minn[1]=a1[1];
    while(!q.empty())
    {
        u=q.front();
        vis[u]=false;
        q.pop();
        for(int i=head[u];i!=-1;i=a[i].Next)
        {
            v=a[i].to;
            if(minn[v]>min(a1[v],minn[u]))
            {
                minn[v]=min(a1[v],minn[u]);
                if(!vis[v])
                {
                    q.push(v);
                    vis[v]=true;
                }
            }
        }
    }
}
void spfa2()
{
    int u,v;
    memset(maxn,0,sizeof(maxn));
    memset(vis,false,sizeof(vis));
    q.push(n);
    vis[n]=true;
    maxn[n]=a1[n];
    while(!q.empty())
    {
        u=q.front();
        vis[u]=false;
        q.pop();
        for(int i=headf[u];i!=-1;i=a[i].Next)
        {
            v=a[i].to;
            if(maxn[v]<max(a1[v],maxn[u]))
            {
                maxn[v]=max(a1[v],maxn[u]);
                if(!vis[v])
                {
                    q.push(v);
                    vis[v]=true;
                }
            }
        }
    }
}
void print()
{
    int ans=0;
    for(int i=1;i<=n;i++)
        minn[i]=min(minn[i],a1[i]);
    for(int i=1;i<=n;i++)
    {
        if(maxn[i]-minn[i]>ans)
            ans=maxn[i]-minn[i];
    }
    cout<<ans<<endl;
}
void solve()
{
    spfa1();
    spfa2();
    print();
}
int main()
{
    memset(head,-1,sizeof(head));
    memset(headf,-1,sizeof(headf));
    read();
    solve();
    return 0;
}
代码在这

 

posted @ 2015-11-03 19:07  HELLO----WORLD  阅读(210)  评论(0编辑  收藏  举报