zoukankan      html  css  js  c++  java
  • 乘车路线「二维spfa」

    乘车路线「二维spfa」

    题目描述

    编号为 1NN 座城镇用若干仅供单向行驶的道路相连,每条道路上均有两个参数:道路长度(length)和在该条道路上行驶的费用(cost)。BOB准备从城镇 1 出发到达城镇 N,但他目前只有 W 的钱,为此,你需要帮助他寻找一条从城镇 1 到城镇 N在他能支付的前提下的一条最短路线。

    输入

    W N MN为城镇数目,2<=N<=100M 为道路条数,1<=M<=10000,W 为钱的数目,0<=W<=1000)随后的 M行每行为一条道路的信息,包含 4 个数值(u,v,w,cost),表示从城镇 uv 有一条长度为 w 的单向道路,经过这条道路需要花费 cost 。(1<=u,v<=N,1<=w<=100,0<=cost<=100)

    输出

    输出最短长度,若无解,则输出“NO ”;

    样例输入

    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

    思路分析

    • 乍一眼看去,最短路啊,再看一眼,诶?有问题,还多了一个限制条件就离谱
    • 考试时直接按边权和钱数分别跑了两遍spfa,后来才发现正确性是不对的(更离谱的是竟然水过了80分,最离谱的是有人暴搜AC了???)。
    • 那么正确思路是什么?两个一起跑呗,一个二维spfa就彳亍,用到了一个本蒟蒻没用过的pair

    详见代码

    代码

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    
    using namespace std;
    const int maxn = 100+10,maxm = 1e4+10,inf = 0x3f3f3f3f;
    int w,n,m;
    int dis[maxn][1005],mon[maxn],ans[maxn],head[maxm],vis[maxn][1005];
    struct edge{
    	int to,next,w,cost;
    }e[maxm];
    int len;
    void addedge(int u,int v,int x,int y){
    	e[++len].to = v;
    	e[len].w = x;
    	e[len].cost = y;
    	e[len].next = head[u];
    	head[u] = len;
    }
    void spfa(int x){ //注意dis,vis都开二维
    	memset(dis,0x3f,sizeof(dis));
    	queue< pair<int,int> >q; //队列里存储的是pair
    	dis[x][0] = 0;
    	q.push(make_pair(x,0)); //用一个pair把dis和money一起压进去
    	while(!q.empty()){
    		pair<int,int> t = q.front();q.pop();
    		int u = t.first,money = t.second;
    		vis[u][money] = 0;
    		for(int i = head[u];~i;i = e[i].next){
    			int v = e[i].to;
    			if(money+e[i].cost>w)continue; //钱不够跑
    			if(dis[v][money+e[i].cost]>dis[u][money]+e[i].w){ //钱够跑并且可以松弛
    				dis[v][money+e[i].cost]=dis[u][money]+e[i].w;
    				if(!vis[v][money+e[i].cost]){
    					vis[v][money+e[i].cost] = 1;
    					q.push(make_pair(v,money+e[i].cost));
    				}
    			}
    		}
    	}
    }
    
    int main(){
    	scanf("%d%d%d",&w,&n,&m);
    	memset(head,-1,sizeof(head));
    	for(int i = 1;i <= m;i++){
    		int a,b,c,d;scanf("%d%d%d%d",&a,&b,&c,&d);
    		addedge(a,b,c,d);
    	}
    	spfa(1);
    	int ans = inf;
    	for(int i = 0;i <= w;i++)ans = min(ans,dis[n][i]);
    	ans==inf ? printf("NO") : printf("%d",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    vue-webpack介绍
    vue-ES6模块化的导入和导出
    vue-前端模块化
    vue-插槽作用域的使用
    vue-具名插槽的使用
    vue-插槽的基本使用
    vue-父组件获取子组件对象实例
    IO(六)
    IO(五)
    关于overflow:hidden
  • 原文地址:https://www.cnblogs.com/hhhhalo/p/13337627.html
Copyright © 2011-2022 走看看