版权声明:本篇随笔版权归作者Etta(http://www.cnblogs.com/Etta/)所有,转载请保留原地址!
问题描述
Nc回到教室上化学课,化学老师为了考考他, 拿来了好多试验用的药品. 他告诉了nc一开始的物质, m个化学方程式, 和他最终需要的产物, 让nc制作出来. 化学老师把一开始的物质编号为1, 最终产物编号为n. 所有可能出现的中间产物从2到n-1编号. 每次把一个物质变成另一个物质, 需要加入一些溶液, 反应需要一定的时间, 并且会产生一些花费. 化学老师说, 他只给nc k元, 让nc在资金范围内尽快完成实验.并告诉他这个最短时间.
输入文件
第一行包含一个整数k, 为nc的资金.
第二行包含一个整数n, 为物质总数.第三行包含一个整数m, 为老师给的化学方程式的个数.接下来m行, 每行包含4个整数a,b,t,c.表示物质a可以变成物质b, 需要t的时间, c的花费.输出文件
如果nc无法完成实验, 输出-1. 否则输出资金允许的最短时间.
样例输入
5
6
7
1 2 2 3
2 4 3 3
3 4 2 4
1 3 4 1
4 6 2 1
3 5 2 0
5 4 3 2
样例输出
11
输入输出样例解释
Nc先花4的时间1的花费将1物质变成3物质, 然后花2的时间0的花费将3物质变成5物质. 接着花3的时间2的花费将5物质变成4物质, 最后花2的时间1的花费将4物质变成6物质.
总时间=4+2+3+2=11; 总花费=1+0+2+1=4<5.
数据范围和约定
对于20% 的数据, n<=12.对于100% 的数据, 0<=k<=10000, 2<=n<=100,1<=m<=10000,0<=t<=100,0<=c<=100.
一、分析问题
这是一个二维最短路问题。
二、解决问题
Pair队列的二维处理+SPFA
Tips:同类型题:LightOJ 1281
三、代码实现
1 #include<cstdio> 2 #include<queue> 3 using namespace std; 4 5 const int A=10010,B=110,inf=4e8; 6 7 typedef pair<int,int>pii; 8 int n,m,k,a,b,tt,cc,sum; 9 int dis[B][A],ex[B][A],head[B]; 10 struct edge{ 11 int to,nxt,t,c; 12 }e[A*2]; 13 queue<pii>q; 14 15 void build(int a,int b,int t,int c) 16 { 17 e[++sum].to=b; 18 e[sum].t=t; 19 e[sum].c=c; 20 e[sum].nxt=head[a]; 21 head[a]=sum; 22 } 23 24 void SPFA() 25 { 26 for(int i=1;i<=n;++i) 27 for(int j=0;j<=k;++j) 28 dis[i][j]=inf; 29 30 dis[1][0]=0;ex[1][0]=1; 31 pii r; 32 r.first=1; 33 r.second=0; 34 q.push(r); 35 while(!q.empty()) 36 { 37 pii j=q.front(); 38 q.pop(); 39 int u=j.first,s=j.second; 40 ex[u][s]=0; 41 for(int i=head[u];i;i=e[i].nxt) 42 { 43 int w=e[i].t,c=e[i].c+s,to=e[i].to; 44 if(dis[to][c]>dis[u][s]+w&&c<=k) 45 { 46 dis[to][c]=dis[u][s]+w; 47 if(!ex[to][c]) 48 { 49 ex[to][c]=1; 50 r.first=to; 51 r.second=c; 52 q.push(r); 53 } 54 } 55 } 56 } 57 } 58 59 int main() 60 { 61 scanf("%d%d%d",&k,&n,&m); 62 for(int i=1;i<=m;++i) 63 { 64 scanf("%d%d%d%d",&a,&b,&tt,&cc); 65 build(a,b,tt,cc); 66 } 67 SPFA(); 68 int minn=inf; 69 for(int i=0;i<=k;++i) 70 if(dis[n][i]<minn)minn=dis[n][i]; 71 if(minn==inf)printf("-1"); 72 else printf("%d ",minn); 73 return 0; 74 }