POJ 2263 Heavy Cargo (SPFA+Dijkstra,最短路变形)

题目链接: POJ 2263 Heavy Cargo


【题目大意】

某公司生产了一种巨型卡车,它的载重量并不在于它本身的载重量, 而只在于公路的载重量!

题目给你 开车运送的起点和终点 , 以及一些可供选择的道路, 每个道路标明了载重量。

让你求出从起点开到终点,卡车的最大载重量是多少 , 也就是起点到终点的通路中,载重量最小的道路的载重量。


【思路】


小技巧: 用map 实现字符串与数字的对应,注意要从1开始。

Dijkstra算法的变形 。

之前学图论的时候这个算法学的太快 没怎么练过,,以为用SPFA完全可以替代,,然而这两种算法的思想并不一样。


Dijkstra算法是从起点开始 ,每次在它相邻的节点中选出距离起点最近的那个点,更新时,将刚选出的节点临近的节点“显化”,也就是将minDist【】的值从INF 更新为当前到起点的距离,  缺点是要遍历n个节点 来找临近的点; 效率 O(n^2)


SPFA算法仅仅把比当前距离短的节点推入队列,再不断的从子节点中通过 松弛操作 找出当前的最短路。


本题是最短路的变形,, 每次寻找的是当前节点 附近节点的最大值而不是最短路,因为要让载重量尽可能的大,用Dijkstra的贪心思想很好想到,


int tmpmin = 0;
int addnode;
for(int i=1;i<=n;i++){
	if(!inqueue[i]&&minDist[i]>tmpmin){ 找出临近节点最大的值
		tmpmin = minDist[i];
		addnode = i;
	}
}


在节点更新的时候 minDist【】 并不是储存当前最短距离了,而是当前最小的载重量。

所以更新的时候 用临近节点的载重量 与 根节点(刚添加的节点)的载重量 比较选出最小的。

for(int i=0;i<G[addnode].size();i++){
          int vex = G[addnode][i].v;
          int value = G[addnode][i].len;
          if(!inqueue[vex]&&minDist[vex]<min(value,minDist[addnode])){
                minDist[vex]=min(value,minDist[addnode]);
          }
  }


【Dijkstra】

#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 220; 
struct node{
	int v,len;
	node(int v=0,int len=0):v(v),len(len){}
};
int minDist[maxn];
bool inqueue[maxn];
vector<node>G[maxn];
int  n,m;
void dijkstra(int st,int end){
	memset(minDist,0,sizeof(minDist));
	memset(inqueue,0,sizeof(inqueue));
	minDist[st]=0;
	inqueue[st]=true;
	for(int i=0;i<G[st].size();i++){
		int vex = G[st][i].v;
		minDist[vex]=G[st][i].len;
	}
	for(int nodenum=1;nodenum<n;nodenum++){
		int tmpmin = 0;
		int addnode;
		for(int i=1;i<=n;i++){
			if(!inqueue[i]&&minDist[i]>tmpmin){
				tmpmin = minDist[i];
				addnode = i;
			}
		}
		inqueue[addnode]=true;
		for(int i=0;i<G[addnode].size();i++){
			int vex = G[addnode][i].v;
			int value = G[addnode][i].len;
			if(!inqueue[vex]&&minDist[vex]<min(value,minDist[addnode])){
				minDist[vex]=min(value,minDist[addnode]);
			}
		}
	}
}
int main(){
	map<string,int>mp; //
	int cas=0;
	while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
		printf("Scenario #%d\n",++cas);
		string a,b;
		mp.clear();
		for(int i=0;i<maxn;i++)
			G[i].clear();
		int len;
		int cnt=0;
		for(int i=0;i<m;i++){
			cin>>a>>b>>len;
			if(!mp[a]){ //用map 做string 与 int对应的时候,不要从0 开始 ,不好判断
				mp[a]=++cnt; //从零开始 这个判断就错了
			}
			if(!mp[b])
				mp[b]=++cnt;
			G[mp[a]].push_back(node(mp[b],len));
			G[mp[b]].push_back(node(mp[a],len));
		}
		cin>>a>>b;
		dijkstra(mp[a],mp[b]);
		cout<<minDist[mp[b]]<<" tons"<<endl<<endl;
	}
	return 0;
}


搞懂了上述传递状态的方法,SPFA的代码就很容易写出来了


【SPFA】

#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
#include <queue>
#include <vector>
#define INF 0xfffffff
using namespace std;
const int maxn = 220; 
struct node{
	int v,len;
	node(int v=0,int len=0):v(v),len(len){}
};
int minDist[maxn];
bool inqueue[maxn];
vector<node>G[maxn];
int  n,m;
void SPFA(int st,int end){
	memset(minDist,0,sizeof(minDist));
	memset(inqueue,0,sizeof(inqueue));
 
    inqueue[st]=true;  
    queue<int >Q;  
    minDist[st]=INF;  
    Q.push(st);  
    while(!Q.empty()){  
        int vex = Q.front();  
        Q.pop();  
        inqueue[vex]=0;  
        for(int i=0;i<G[vex].size();i++){  
            int v = G[vex][i].v;  
			int value = G[vex][i].len;
			int tmp = max(minDist[v],min(minDist[vex],value));
            if(tmp>minDist[v]){  
                minDist[v]=tmp;
                if(!inqueue[v])  
                {  
                    inqueue[v]=1;  
                    Q.push(v);  
                }  
            }  
                  
        }  
    }  
}
int main(){
	map<string,int>mp; //
	int cas=0;
	while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){
		printf("Scenario #%d\n",++cas);
		string a,b;
		mp.clear();
		for(int i=0;i<maxn;i++)
			G[i].clear();
		int len;
		int cnt=0;
		for(int i=0;i<m;i++){
			cin>>a>>b>>len;
			if(!mp[a]){ //用map 做string 与 int对应的时候,不要从0 开始 ,不好判断
				mp[a]=++cnt; //从零开始 这个判断就错了
			}
			if(!mp[b])
				mp[b]=++cnt;
			G[mp[a]].push_back(node(mp[b],len));
			G[mp[b]].push_back(node(mp[a],len));
		}
		cin>>a>>b;
		SPFA(mp[a],mp[b]);
		cout<<minDist[mp[b]]<<" tons"<<endl<<endl;
	}
	return 0;
}


这一题在比赛的时候没有想出来怎么写,还是对算法原理掌握的不够清晰,光看模板是敲不出来新题的!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值