标签:style blog color io ar for div log sp
给出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 }
标签:style blog color io ar for div log sp
原文地址:http://www.cnblogs.com/wshh/p/3943986.html