Luogu P1073 最优贸易

4 篇文章 0 订阅
Luogu P1073 最优贸易

感觉是一道很友善的蓝题 图论都很友善qwq

一开始看题,以为可以多次买卖,一想,惨了,DP:-(
然后在扫了一遍发现原来只进行最多一次买卖
那贪心吧,该怎么贪。。。
就是找水晶球最贵最便宜城市吧,但不一定联通啊。。。
难道排序之后按大到小枚举卖的城市,按小到大枚举买的城市?然后问一下可不可以跑得到???这样子吗。。。可以实现吗 肯定不可以啊
于是又膜了题解
很妙啊原来也不难
看了思路觉得特别友善啊 颇为开心的就开始打了
好像之前的题都比这个难啊quq果然还是我太弱了
昨天打了一个中午,60.。。
今天终于查出错了然后A了

大概思路

跑两次spfa一次从头开始,
一次从尾开始,记录最小值和最大值,
第二次跑的时候不断问每一个点最大值和最小值的差,
最大的差就是answer!:建边时要建反向边,分开两张图跑
对于每个点的最小值:是从起点跑到这所经过的城市中水晶球最低的价格
最大值:是从终点跑到这所经过的城市中水晶球最高的价格
#include<cstdio>
#include<cstring>

int n,m,len,lenn;
int ans=0,first[100100],ffirst[100100];
int a[100100],v[100100],f[100100],sum1[100010],sum2[100010];
struct nod1{int x,y,next;}b[1000010],c[1000010];

int minn(int x,int y)
{
    return x<y?x:y;
}

int maxx(int x,int y)
{
    return x>y?x:y;
}

int ins(int x,int y)
{
    len++;
    b[len].x=x;
    b[len].y=y;
    b[len].next=first[x];
    first[x]=len;
}

int iins(int x,int y)
{
    lenn++;
    c[lenn].x=x;
    c[lenn].y=y;
    c[lenn].next=ffirst[x];
    ffirst[x]=lenn;
}

int spfa1()
{
    int st=1,ed=2;
    f[st]=1;
    sum1[1]=a[1];
    v[1]=1;
    while(st!=ed)
    {
        int x=f[st];
        for(int i=first[x];i;i=b[i].next)
        {
            int y=b[i].y;
            if(sum1[y]>sum1[x]||sum1[y]>a[y])
            {
                sum1[y]=minn(a[y],sum1[x]);
                if(v[y]==0)
                {
                    v[y]=1;
                    f[ed]=y;
                    ed++;
                }
            }
        }
        st++;
        v[x]=0;
    }
}
int spfa2()
{
    int st=1,ed=2;
    memset(f,0,sizeof(0));
    memset(v,0,sizeof(v));
    f[st]=n;
    sum2[n]=a[n];
    v[n]=1;
    ans=maxx(ans,sum2[n]-sum1[n]);
    while(st!=ed)
    {
        int x=f[st];
        for(int i=ffirst[x];i;i=c[i].next)
        {
            int y=c[i].y;
            if(sum2[y]<sum2[x]||sum2[y]<a[y])
            {
                sum2[y]=maxx(sum2[x],a[y]);
                ans=maxx(ans,sum2[y]-sum1[y]);
                if(v[y]==0)
                {
                    v[y]=1;
                    f[ed]=y;
                    ed++;
                }
            }
        }
        st++;
        v[x]=0;
    }
}

int main()
{
    //freopen("aa.in","r",stdin);
    memset(sum1,63,sizeof(sum1));
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);sum1[i]=99999999;
    }
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d %d %d",&x,&y,&z);
        if(z==1)
        {
            ins(x,y);
            iins(y,x);
        }
        if(z==2)
        {
            ins(x,y);ins(y,x);
            iins(x,y);iins(y,x);
        }
    }
    spfa1();
    spfa2();
    printf("%d",ans);
}

思维力还是不够啊。。。
这个也是翻了题解的(好像什么题都翻了)。。。
自己想的总是又被自己推翻,还是太菜了。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值