zoj 3794 Greedy Driver(最短路)

来源:互联网 发布:icloud软件下载 编辑:程序博客网 时间:2024/06/05 09:57

题意:一个人要从1走到n,他有一个加油卡,可以再任意一个有加油站的地方免费加油,走每条道路要花费一定的汽油,有一些城市可以卖汽油赚钱,他想要在能到达n的前提下,尽量赚更多的钱,但是他只能卖一次汽油,问这个人能获得的最大收益是多少。

思路:求两次最短路,第一次从起点开始,求从起点到达这个位置时能保留的最多的汽油的量,另一次从终点开始,计算从某一点到达终点至少需要多少汽油。然后就可以枚举一下可以卖汽油的位置,将第一次得到的值减去第二次得到的值就是能卖掉的最多的汽油了。


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#include<bitset>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-6#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=1000+10;const int maxm=100000+10;struct Edge{    int v,w,next;    Edge(){}    Edge(int v,int w,int next):v(v),w(w),next(next){}}edges[maxm<<1];int head[maxn],dmax[maxn],dmin[maxn],nEdge;int fuel[maxn],sell[maxn],n,m,C;bool inq[maxn];void AddEdges(int u,int v,int w){    edges[++nEdge]=Edge(v,w,head[u]);    head[u]=nEdge;    edges[++nEdge]=Edge(u,w,head[v]);    head[v]=nEdge;}void fmax(int s){    memset(dmax,0xff,sizeof(dmax));    memset(inq,0,sizeof(inq));    queue<int>q;    q.push(s);    dmax[s]=C;    while(!q.empty())    {        int u=q.front();q.pop();        inq[u]=false;        for(int k=head[u];k!=-1;k=edges[k].next)        {            if(dmax[u]<edges[k].w||(k&1)) continue;            int v=edges[k].v;            if(dmax[v]<dmax[u]-edges[k].w)            {                if(fuel[v]) dmax[v]=C;                else dmax[v]=dmax[u]-edges[k].w;                if(!inq[v]) {inq[v]=true;q.push(v);}            }        }    }}void fmin(int s){    memset(dmin,0x3f,sizeof(dmin));    memset(inq,0,sizeof(inq));    queue<int>q;    q.push(s);    dmin[s]=0;    while(!q.empty())    {        int u=q.front();q.pop();        inq[u]=false;        for(int k=head[u];k!=-1;k=edges[k].next)        {            if(dmin[u]+edges[k].w>C||(k%2==0)) continue;            int v=edges[k].v;            if(dmin[v]>dmin[u]+edges[k].w)            {                if(fuel[v]) dmin[v]=0;                else dmin[v]=dmin[u]+edges[k].w;                if(!inq[v]) {inq[v]=true;q.push(v);}            }        }    }}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    while(~scanf("%d%d%d",&n,&m,&C))    {        memset(head,0xff,sizeof(head));        memset(fuel,0,sizeof(fuel));        memset(sell,0,sizeof(sell));        nEdge=-1;        int u,v,w;        for(int i=0;i<m;++i)        {            scanf("%d%d%d",&u,&v,&w);            AddEdges(u,v,w);        }        int P,Q;        scanf("%d",&P);        while(P--)        {            scanf("%d",&u);            fuel[u]=1;        }        scanf("%d",&Q);        while(Q--)        {            scanf("%d%d",&u,&w);            sell[u]=w;        }        fmax(1);        fmin(n);        int ans=0,tmp;        for(int i=1;i<=n;++i)            if(sell[i]&&dmax[i]!=-1&&dmin[i]!=inf)            {                tmp=(dmax[i]-dmin[i])*sell[i];                ans=max(ans,tmp);            }        if(dmax[n]==-1) ans=-1;        printf("%d\n",ans);    }    return 0;}


0 0