两次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\n",ans);
}
}
return 0;
}

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

ZOJ 3794 Greedy Driver的更多相关文章

  1. ZOJ 3794 Greedy Driver spfa

    题意: 给定n个点,m条有向边,邮箱容量. 起点在1,终点在n,開始邮箱满油. 以下m行表示起点终点和这条边的耗油量(就是长度) 再以下给出一个数字m表示有P个加油站,能够免费加满油. 以下一行P个数 ...

  2. ZOJ Monthly, June 2014 月赛BCDEFGH题题解

    比赛链接:点击打开链接 上来先搞了f.c,,然后发现状态不正确,一下午都是脑洞大开,, 无脑wa,无脑ce...一样的错犯2次.. 硬着头皮搞了几发,最后20分钟码了一下G,不知道为什么把1直接当成不 ...

  3. ZOJ Monthly, June 2014 解题报告

    A.Another Recurrence Sequence problemId=5287">B.Gears 题目大意:有n个齿轮,一開始各自为一组.之后进行m次操作,包含下面4种类型: ...

  4. 深入linux kernel内核配置选项

    ============================================================================== 深入linux kernel内核配置选项 ...

  5. 重拾ZOJ 一周解题

    ZOJ 2734 Exchange Cards 题目大意: 给定一个值N,以及一堆卡片,每种卡片有一个值value和数量number.求使用任意张卡片组成N的方式. 例如N = 10 ,cards(1 ...

  6. ZOJ 2475 Benny's Compiler(dfs判断有向图给定点有没有参与构成环)

    B - Benny's Compiler Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu ...

  7. MongoDB Java Driver操作指南

    MongoDB为Java提供了非常丰富的API操作,相比关系型数据库,这种NoSQL本身的数据也有点面向对象的意思,所以对于Java来说,Mongo的数据结构更加友好. MongoDB在今年做了一次重 ...

  8. c#操作MangoDB 之MangoDB CSharp Driver驱动详解

    序言 MangoDB CSharp Driver是c#操作mongodb的官方驱动. 官方Api文档:http://api.mongodb.org/csharp/2.2/html/R_Project_ ...

  9. Java JDBC Thin Driver 连接 Oracle 三种方法说明(转载)

    一.JDBC 连接Oracle 说明 JDBC 的应用连接Oracle 遇到问题,错误如下: ORA-12505,TNS:listener does not currently know of SID ...

随机推荐

  1. JAVA面试中问及HIBERNATE与 MYBATIS的对比,在这里做一下总结(转)

    hibernate以及mybatis都有过学习,在java面试中也被提及问道过,在项目实践中也应用过,现在对hibernate和mybatis做一下对比,便于大家更好的理解和学习,使自己在做项目中更加 ...

  2. “/” 应用程序中的服务器错误 - IIS 发布错误

    解决方法, 将bin目录下的全部文件复制到iis下

  3. hihocoder1302 最长回文子串

    hihocoder1302 最长回文子串 先贴代码 所有的上面的提示已经交代的好清楚了…… #include <iostream> #include <cstring> #in ...

  4. Android Content Provider的启动过程源码分析

    本文參考Android应用程序组件Content Provider的启动过程源码分析http://blog.csdn.net/luoshengyang/article/details/6963418和 ...

  5. UVA 322 ships (POJ 1138)

    题目地址: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

  6. HDU 5046 Airport(DLX反复覆盖)

    HDU 5046 Airport 题目链接 题意:给定一些机场.要求选出K个机场,使得其它机场到其它机场的最大值最小 思路:二分+DLX反复覆盖去推断就可以 代码: #include <cstd ...

  7. asp.net2.0安全性(1)--用户角色篇(代码实现1)--转载来自车老师

    创建用户: MembershipCreateStatus mc; Membership.CreateUser(txtUid.Text, txtPwd.Text, txtEmail.Text, txtQ ...

  8. Eclipse用法和技巧七:自动生成get和set方法2

    上一篇文章中我们介绍了自动批量生成get和set函数的方法.这个方法一般在声明完类的数据域之后使用,比较方便快捷.这里再补充几个自动生成get和set函数的方法. 步骤一:在声明的数据域中按Ctrl+ ...

  9. COM实现过程

    前言 COM已经成为一个必需的东西了.在我们周围,可以说处处充满了COM – 如果你是在使用WINDOWS,并在其下面编写程序的话.然而,无论你是用VC,还是使用DELPHI进行COM编程时,在大多数 ...

  10. oracle for update和for update nowait(for update wait)的区别

    1.for update 和 for update nowait 的区别: 1.oracle 中执行select 操作读取数据不会有任何限制,当另外一个进程在修改表中的数据,但是并没有commit,所 ...