zoukankan      html  css  js  c++  java
  • zoj 3794 Greedy Driver

    给出n个点,m条有向边,Edward驾车要从点1到点n,车的满油量是c,在n个点中有p个点是加油站,Edward每到一个加油站都可以加满油(不用钱),每条边都有个权值L,表示通过这条边至少要有L个单位的油。然后题目给出了Q个点,在这Q个点Edward可以卖掉一些油,第qi个点油价格为vi,但是前提是他还能够到底第n个点,而且只能选择在Q个点中的一个点卖掉一些。题目则要求出Edward卖油所得钱的最大值。

    对与Q个可以卖油的点,每个点可以得到(从1到qi最多剩多少油-从qi要到n点至少需要多少油)*vi。枚举则可得到最大值。而括号里的两个值,则可通过两次spfa求得(第二次要建反向图)。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int inf=0x3f3f3f3f;
     4 const int maxn=100005;
     5 int n,m,c,p,q;
     6 bool station[1005];
     7 bool inq[1005];
     8 struct edge{
     9     int v,w,p;
    10     edge(){}
    11     edge(int v,int w,int p):v(v),w(w),p(p){}
    12 }e[maxn<<1];
    13 int head1[1005],head2[1005];
    14 int d1[1005],d2[1005];
    15 int ecnt;
    16 void spfa(int st,int ed,int head[],int d[]){
    17     for(int i=1;i<=n;i++)d[i]=i==st?0:inf;
    18     queue<int>q;
    19     q.push(st);
    20     memset(inq,0,sizeof inq);
    21     inq[st]=1;
    22     while(!q.empty()){
    23         int u=q.front();q.pop();
    24         inq[u]=0;
    25         for(int i=head[u];i!=-1;i=e[i].p){
    26             int v=e[i].v;
    27             int tmp=d[u]+e[i].w;
    28             if(tmp<=c){
    29                 if(station[v])tmp=0;//当当前点是加油站,则更新d[v]为0;
    30                 if(tmp<d[v]){
    31                     d[v]=tmp;
    32                     if(!inq[v]){
    33                         inq[v]=1;
    34                         q.push(v);
    35                     }
    36                 }
    37             }
    38         }
    39     }
    40 }
    41 void run(){
    42     memset(head1,-1,sizeof head1);
    43     memset(head2,-1,sizeof head2);
    44     ecnt=0;
    45     while(m--){
    46         int u,v,w;
    47         scanf("%d%d%d",&u,&v,&w);
    48         if(w>c)continue;
    49         e[ecnt]=edge(v,w,head1[u]);
    50         head1[u]=ecnt++;
    51         e[ecnt]=edge(u,w,head2[v]);//建反向边
    52         head2[v]=ecnt++;
    53     }
    54     scanf("%d",&p);
    55     memset(station,0,sizeof station);
    56     while(p--){
    57         int x;
    58         scanf("%d",&x);
    59         station[x]=1;     //标记加油站
    60     }
    61     spfa(1,n,head1,d1);
    62     spfa(n,1,head2,d2);//两次spfa
    63     int ans=0;
    64     scanf("%d",&q);
    65     while(q--){
    66         int x,v;
    67         scanf("%d%d",&x,&v);
    68         if(c-d1[x]-d2[x]>0)ans=max(ans,(c-d1[x]-d2[x])*v);//对于Q个卖油点,更新答案
    69     }
    70     if(d1[n]==inf)ans=-1;//不能到达,输出-1
    71     cout<<ans<<endl;
    72 }
    73 int main()
    74 {
    75 //    freopen("in","r",stdin);
    76     while(cin>>n>>m>>c)run();
    77     return 0;
    78 }
  • 相关阅读:
    Volley(二)—— 基本Request对象 & RequestQueue&请求取消
    进程ps、kill 、grep
    vi常用命令
    查看linux系统版本
    linux下U盘的读取
    linux下文件夹的创建、复制、剪切、重命名、清空和删除命令
    Python 列表
    Python 数据运算
    Python pyc知识了解
    Python for循环
  • 原文地址:https://www.cnblogs.com/wshh/p/3943986.html
Copyright © 2011-2022 走看看