ZOJ 2027 floyd(条件松弛)+spfa解法

另一道相似的floyd+dp题目:      博客戳这里        zoj 1232  哪道题可以瞬移很多次,好比这里的省去一个机票,想用floyd+dp的去戳←←...


因为这道题只去掉一个机票

所以并不一定要用dp+floyd.,只要加上条件松弛就可以省去dp了。

开两个数组分别存储路途总价格和路途最大机票价格即可用floyd

graph[i][j]:=存放i->j的总机费,并非答案

maxn[i][j]:=存在i->j路途最大的飞机票费用

答案为:graph[1][2]-maxn[1][2]

代码注释:

void floyd()  //总的费用和最大机票价格分别存储即可省去DP
{
	for(int k=1;k<num;k++)
		for(int i=1;i<num;i++)
			for(int j=1;j<num;j++)
			{
				int temp=graph[i][k]+graph[k][j]-max(maxn[i][k],maxn[k][j]);  //i->k->j的总价格减去最大的机票价格(i->k,k->j)
				if(temp<graph[i][j]-maxn[i][j])  //如果大于 i->j的总价格减去i->j最大的机票价格的费用,则松弛
				{
					graph[i][j]=graph[i][k]+graph[k][j];  //graph储存的是松弛后的i->j总的费用,并没有减钱。
					maxn[i][j]=max(maxn[i][k],maxn[k][j]);//储存松弛后的 i->j的最大机票价格
				}
			}
}
floyd代码:

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <vector>
#include <cstdio>
#include <string>
#include<string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int graph[300][300],maxn[300][300];
int n,cost,num=3;
char ch1[100],ch2[100];
void init()
{
	map<string,int>getid;
	memset(maxn,0,sizeof(maxn));
	for(int i=0;i<300;i++)
		for(int j=0;j<300;j++)
			graph[i][j]=10000000;
	getid[ch1]=1;
	getid[ch2]=2;
	scanf("%d",&n);
	while(n--)
	{
		scanf("%s %s %d",ch1,ch2,&cost);
		if(getid[ch1]==0)
			getid[ch1]=num++;
		if(getid[ch2]==0)
			getid[ch2]=num++;
		graph[getid[ch1]][getid[ch2]]=cost;
		maxn[getid[ch1]][getid[ch2]]=cost;
	}
}
void floyd()
{
	for(int k=1;k<num;k++)
		for(int i=1;i<num;i++)
			for(int j=1;j<num;j++)
			{
				int temp=graph[i][k]+graph[k][j]-max(maxn[i][k],maxn[k][j]);
				if(temp<graph[i][j]-maxn[i][j])
				{
					graph[i][j]=graph[i][k]+graph[k][j];
					maxn[i][j]=max(maxn[i][k],maxn[k][j]);
				}
			}
}
int main()
{
	while(~scanf("%s\n%s",ch1,ch2))  //多组数据- - wa一次。
	{	
		init();
		floyd();
		printf("%d\n",graph[1][2]-maxn[1][2]);
	}
	return 0;
}


spfa:也差不多是分别存储得出答案

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <math.h>
#include <vector>
#include <cstdio>
#include <string>
#include<string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int graph[300][300],maxn[300][300];
int n,cost,num=3;
char ch1[100],ch2[100];
void init()
{
	map<string,int>getid;
	memset(maxn,0,sizeof(maxn));
	for(int i=0;i<300;i++)
		for(int j=0;j<300;j++)
			graph[i][j]=10000000;
	getid[ch1]=1;
	getid[ch2]=2;
	scanf("%d",&n);
	while(n--)
	{
		scanf("%s %s %d",ch1,ch2,&cost);
		if(getid[ch1]==0)
			getid[ch1]=num++;
		if(getid[ch2]==0)
			getid[ch2]=num++;
		graph[getid[ch1]][getid[ch2]]=cost;
		maxn[getid[ch1]][getid[ch2]]=cost;
	}
}
void spfa()
{
	bool vis[300];
	int dist[300];
	memset(vis,0,sizeof(vis));
	for(int i=1;i<num;i++)
		dist[i]=1000000;
	vis[1]=1;
	dist[1]=0;
	queue<int>que;
	que.push(1);
	while(!que.empty())
	{
		int v=que.front();  //v为中间点,相当于floyd中的第一个循环k
		que.pop();
		vis[v]=0;
		for(int i=1;i<num;i++)
			if(dist[v]+graph[v][i]-max(maxn[1][v],maxn[v][i])<dist[i]-maxn[1][i])//dist[v]相当于上代码的graph[1][v].
			{
				dist[i]=dist[v]+graph[v][i];  //分别存储
				maxn[1][i]=max(maxn[1][v],maxn[v][i]);  //分别存储
				if(!vis[i])
				{
					vis[i]=1;
					que.push(i);
				}
			}
	}
	printf("%d\n",dist[2]-maxn[1][2]);
}
int main()
{
	while(~scanf("%s\n%s",ch1,ch2))
	{	
		init();
		spfa();
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值