• ZOJ 3794 Greedy Driver



    两次SPFA

    第一关找:从1没有出发点到另一个点的多少是留给油箱

    把边反过来再找一遍:重每一个点到终点最少须要多少油


    Greedy Driver

    Time Limit: 2 Seconds      Memory Limit: 65536 KB

    Edward is a truck driver of a big company. His daily work is driving a truck from one city to another. Recently he got a long distance driving work, so he may be needed to add fuel to his truck on the way. His boss gives him a fuel card, he can use the card anytime at any fuel station and add any amount of fuel. He does not spend any money when he uses the card. He noticed that there are some cities where he could sell fuel. The greedy driver Edward want to make some money while he doing this work. And this is his plan:

    There are N cities on his map and numbered from 1 to N, he need to drive from city 1 to city N to finish this task. Driving from one city to another need fuel cost too. There are some of the cities has fuel station, he could use his fuel card at these cities. Notice his truck has a fuel tank capacity C and it could not exceed the capacity when add fuel. At the beginning, he is at city 1 and he has a full tank.

    At some cities he could sell any amount of fuel he has, and the prices at each city maybe different. Since he does not want to be found, he sell the fuel at most once totally. Under the premise of driving to city N finally, he wants to make the maximal money.

    Input

    There are multiple test cases. For each test case:

    The first line contains three integer N (1 ≤ N ≤ 1000), M (1 ≤ M ≤ 100000), C(1 ≤ C ≤ 30000), N is the number of cities, M is the number of roads, please notice that the roads is single-way, and C is the fuel tank capacity.

    The after M lines describe the roads, each line has three integers AB (1 ≤ AB ≤ N), L (1 ≤ L ≤ 30000). That means the fuel cost from city A to city B is L.

    Then a single line contain one integer P (0 ≤ P ≤ N), it is the number of cities which has a fuel station.

    The after single line contains P integers, each integer pi (1 ≤ pi ≤ N) is a city number means this city has a fuel station.

    Then a single line contain one integer Q (0 ≤ Q ≤ N), it is the number of cities which he could sell fuel.

    Each of the after Q lines contains two integers qi (1 ≤ qi ≤ N), vi (1 ≤ vi ≤ 30000), means the price at city qi is vi. If he sell one unit of fuel, he will get vi money.

    There is a blank line between every two cases.

    Process to the end of input.

    Output

    One line for each test case. The maximal money he could make while doing this task, or -1 if he could not reach city N.

    Sample Input

    5 6 10
    1 2 4
    1 4 1
    4 3 1
    2 5 1
    4 5 2
    3 2 1
    1
    3
    1
    2 2
    

    Sample Output

    16
    

    Author: LI, Huang
    Source: ZOJ Monthly, June 2014



    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    
    const int maxn=110000;
    const int INF=0x3f3f3f3f;
    
    struct Edge
    {
        int to,next,cost;
    }edge[maxn],edge2[maxn];
    
    int Adj[maxn/100],Adj2[maxn/100],Size,Size2;
    int fuel[maxn/100],price[maxn/100],n,m,c,p,q;
    
    void init()
    {
        Size=Size2=0;
        memset(Adj,-1,sizeof(Adj));
        memset(Adj2,-1,sizeof(Adj2));
        memset(fuel,0,sizeof(fuel));
        memset(price,0,sizeof(price));
    }
    
    void Add_Edge(int u,int v,int w)
    {
        edge[Size].next=Adj[u];
        edge[Size].to=v;
        edge[Size].cost=w;
        Adj[u]=Size++;
    }
    
    void Add_Edge2(int u,int v,int w)
    {
        edge2[Size2].next=Adj2[u];
        edge2[Size2].to=v;
        edge2[Size2].cost=w;
        Adj2[u]=Size2++;
    }
    
    int dmax[maxn/100],cq[maxn],dmin[maxn/100];
    bool inq[maxn/100];
    
    bool spfa_find_max()
    {
        memset(dmax,-1,sizeof(dmax));
        memset(cq,0,sizeof(cq));
        memset(inq,false,sizeof(inq));
        dmax[1]=c;
        queue<int> q;
        inq[1]=true,cq[1]=1; q.push(1);
    
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int i=Adj[u];~i;i=edge[i].next)
            {
                int v=edge[i].to;
                if(dmax[u]-edge[i].cost<0) continue;
                if(dmax[v]<dmax[u]-edge[i].cost)
                {
                    if(fuel[v]) dmax[v]=c;
                    else dmax[v]=dmax[u]-edge[i].cost;
                    if(inq[v]==false)
                    {
                        inq[v]=true;
                        cq[v]++;
                        if(cq[v]>=n) return false;
                        q.push(v);
                    }
                }
            }
            inq[u]=false;
        }
        return true;
    }
    
    bool spfa_find_min()
    {
        memset(dmin,63,sizeof(dmin));
        memset(inq,false,sizeof(inq));
        memset(cq,0,sizeof(cq));
        dmin[n]=0;
        queue<int> q;
        q.push(n);
        inq[n]=true,cq[n]=1;
    
        while(!q.empty())
        {
            int u=q.front(); q.pop();
    
            for(int i=Adj2[u];~i;i=edge2[i].next)
            {
                int v=edge2[i].to;
                if(dmin[u]+edge2[i].cost>c) continue;
                if(dmin[v]>dmin[u]+edge2[i].cost)
                {
                    if(fuel[v]) dmin[v]=0;
                    else
                    {
                        dmin[v]=dmin[u]+edge2[i].cost;
                    }
                    if(inq[v]==false)
                    {
                        inq[v]=true;
                        cq[v]++;
                        if(cq[v]>=n) return false;
                        q.push(v);
                    }
                }
            }
            inq[u]=false;
        }
        return true;
    }
    
    int main()
    {
        while(scanf("%d%d%d",&n,&m,&c)!=EOF)
        {
            init();
            for(int i=0;i<m;i++)
            {
                int u,v,x;
                scanf("%d%d%d",&u,&v,&x);
                Add_Edge(u,v,x);
                Add_Edge2(v,u,x);
            }
            scanf("%d",&p);
            for(int i=0;i<p;i++)
            {
                int x; scanf("%d",&x);
                fuel[x]=1;
            }
            scanf("%d",&q);
            for(int i=0;i<q;i++)
            {
                int x,y; scanf("%d%d",&x,&y);
                price[x]=y;
            }
            spfa_find_max();///油箱里最多剩下多少油
            spfa_find_min();///到终点最少须要多少油
            if(dmax[n]==-1||dmin[1]==INF) puts("-1");
            else
            {
                int ans=0;
                for(int i=1;i<=n;i++)
                {
                    if(price[i]&&dmax[i]!=-1&&dmin[i]!=INF)
                    {
                        ans=max(ans,price[i]*(dmax[i]-dmin[i]));
                    }
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    


    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    图像分割学习笔记_1(opencv自带meanshift分割例子)
    基础学习笔记之opencv(10):Mat mask操作
    Qt学习之路_6(Qt局域网聊天软件)
    Qt学习之路_8(Qt中与文件目录相关操作)
    Android开发历程_6(RadioButton和CheckBox的使用)
    Qt学习之路_4(Qt UDP的初步使用)
    目标跟踪学习笔记_4(particle filter初探3)
    Reading papers_11(读Integrating local action elements for action analysis相关文章)
    基础学习笔记之opencv(8):Mat 基本图像容器
    基础学习笔记之opencv(14):随机数发生器&绘制文字
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4669320.html
Copyright © 2020-2023  润新知