题目大意:
给你 N 个点 ,M 条有向路,走每条路需要花费 C 元,这段路的长度为 L 。
给你 K 元,问你能否从 1 走到 N 点且花费不超过 K 元。如果可以,输出出最短距离,否则输出 -1 。
显然分层图最短路,这里 dist[i][j] 表示从 1 到 i 点 且 所剩钱数为 j 时的最短路,然后跑一遍 dijkstra 即可。
PS:在优先队列先到达 N 点的即为答案,可以直接返回,不需要等队列走完再 O(N)找最小值,时间会很快(这里还是遍历了一遍 = =)
代码如下:
#include<iostream> #include<algorithm> #include<string.h> #include<queue> #define inf 0x3f3f3f3f #define maxn 308 using namespace std; int K,N,M,cnt; int head[maxn],ans; bool vis[maxn][10008]; int dist[maxn][10008]; struct Edge { int to; int val; int m; int next; }edge[maxn*maxn]; struct Node { int x; int k; int val; Node(){}; Node(int _x,int _k,int _val){ x=_x,k=_k,val=_val; } bool operator < (const Node a) const{ return val>a.val; } }; inline void add(int u,int v,int val,int m) { edge[++cnt].to=v; edge[cnt].val=val; edge[cnt].m=m; edge[cnt].next=head[u]; head[u]=cnt; return; } void dijkstra() { priority_queue<Node> q; while(!q.empty()) q.pop(); for(int i=1;i<=N;i++){ for(int j=0;j<=K;j++){ dist[i][j]=inf; } } q.push(Node(1,K,0)); dist[1][K]=0; while(!q.empty()) { int u=q.top().x,k=q.top().k; q.pop(); // 这里可以直接 if( u == N) ans = q.top().val ,即为答案 if(vis[u][k]) continue; vis[u][k]=true; for(int i=head[u];i;i=edge[i].next){ int v=edge[i].to; if(k>=edge[i].m){ if(dist[v][k-edge[i].m]>dist[u][k]+edge[i].val){ dist[v][k-edge[i].m]=dist[u][k]+edge[i].val; q.push(Node(v,k-edge[i].m,dist[v][k-edge[i].m])); } } } } return; } int main() { //freopen("test.in","r",stdin); //freopen("test.out","w",stdout); scanf("%d%d%d",&K,&N,&M); int A,B,C,D; while(M--) { scanf("%d%d%d%d",&A,&B,&C,&D); add(A,B,C,D); } ans=inf; dijkstra(); for(int i=0;i<=K;i++){ ans=min(ans,dist[N][i]); } if(ans==inf) printf("-1\n"); else printf("%d\n",ans ); }