toj 2741 Hotel booking (spfa+bfs+巧妙构图)

Description

A transport company often needs to deliver goods from one city to another city. The transport company has made a special deal with a hotel chain which allows its drivers to stay in the hotels of this chain for free. Drivers are only allowed to drive up to 10 hours a day. The transport company wants to find a route from the starting city to the destination city such that a driver can always spend the night in one of the hotels of the hotel chain, and that he needs to drive at most 10 hours from one hotel to the next hotel (or the destination). Of course, the number of days needed to deliver the goods should also be minimized.

Input

The input file contains several test cases. Each test case starts with a line containing an integer n, (2 ≤ n ≤ 10000), the number of cities to be considered when planning the route. For simplicity, cities are numbered from 1 to n, where 1 is the starting city, and n is the destination city. The next line contains an integer h followed by the numbers c1, c2, ..., ch indicating the numbers of the cities where hotels of the hotel chain are located. You may assume that 0 ≤ h ≤ min(n, 100). The third line of each test case contains an integer m (1 ≤ m ≤ 105), the number of roads to be considered for planning the route. The following m lines describe the roads. Each road is described by a line containing 3 integers a, b, t (1 ≤ a, b ≤ n and 1 ≤ t ≤ 600), where a, b are the two cities connected by the road, and t is the time in minutes needed by the driver to drive from one end of the road to the other. Input is terminated by n = 0.

Output

For each test case, print one line containing the minimum number of hotels the transport company has to book for a delivery from city 1 to city n. If it is impossible to find a route such that the driver has to drive at most 10 hours per day, print -1 instead.

Sample Input

6
3 2 5 3
8
1 2 400
3 2 80
3 4 301
4 5 290
5 6 139
1 3 375
2 5 462
4 6 300
3
0
2
1 2 371
2 3 230
0

Sample Output

2
-1

 

思路

这道题的意思是给你n个点,1为起点,n为终点(n<=10000),两者之间有n-2个点,并且其中有m个旅馆,你是个司机,并且每次行驶只能持续600分钟,你可以选择在行驶600分钟之内时到一个旅馆休息。问你是否可以到达终点,如何可以,最少需要再几间旅馆住下。

很明显的可以转化过来,这是一个m+2个点之间的问题,一个起点,一个终点,以及m个旅馆。然后再重新构建一遍,判断两点之间的最短时间,因为时间复杂度的关系,所以这里要用spfa来求两点之间的最短距离是否满足要求,能否再600分钟以内,再重现建立一个都可以连通的图。最后bfs一遍,判断最少可以通过几个点到达终点。

 

 

#include <iostream>
#include <vector>
#include <queue>
#include <map> 
#include <cstring>
using namespace std;
typedef struct Node{
	int p,s;
};
const int N = 1e4+5; 
const int INF = 0x3f3f3f3f;
vector<Node> vec[N];//存边 
map<int,int> ma;//映射旅馆 
int hotel[105];
int t,n,k;
vector<int> G[105];
void spfa(int kk){
	int dis[N],i,j;
	bool vis[N];
	memset(vis,false,sizeof(vis));
    memset(dis,INF,sizeof(dis));
    dis[kk]=0;
    queue<int> que;
    que.push(kk);
    while(!que.empty())
    {
        int u=que.front();
        que.pop();
        vis[u]=0;
        for(i=0;i<vec[u].size();i++)
        {
             Node node=vec[u][i];
             int v=node.p;
             if(dis[v]>dis[u]+node.s)
             {
                dis[v]=dis[u]+node.s;
                if(!vis[v])
                {
                    vis[v]=true;
                    que.push(v);
                }
            }
		}
    }
    if(dis[1]<=600&&kk!=1){
		G[ma[kk]].push_back(ma[1]);
	}
	for(int i=2;i<=t;i++){
		if(dis[i]<=600&&i!=kk&&ma[i]!=0){
			G[ma[kk]].push_back(ma[i]);
		}
	}
}
void bfs(){
	int dis[105];
	for(int i=0;i<105;i++)
		dis[i]=-1;
	queue<int> que;
	que.push(ma[1]);
	while(!que.empty()){
		int u=que.front();
		que.pop();
		for(int i=0;i<G[u].size();i++){
			if(dis[G[u][i]]==-1){
				dis[G[u][i]]=dis[u]+1;
				que.push(G[u][i]);
			}
		}
	}
	cout<<dis[ma[t]]<<endl;	
}
int main() {
	ios::sync_with_stdio(false);
	int i,j,x,y,z;
	while(cin>>t){
		if(t==0)
			break;
		for(i=0;i<N;i++){
			vec[i].clear();
			ma[i]=0;
		} 
		memset(G,0,sizeof(G));
		cin>>k;//旅馆数 
		for(i=1;i<=k;i++){ 
			cin>>hotel[i];
			ma[hotel[i]]=i;
		}
			
		cin>>n;//边数 
		for(i=0;i<n;i++){
			cin>>x>>y>>z;
			Node node1,node2;
			node1.p=y,node1.s=z;
			node2.p=x,node2.s=z;
			vec[x].push_back(node1);
			vec[y].push_back(node2); 
		} 
		ma[1]=0;
		ma[t]=k+1;
		hotel[0]=1;
		hotel[k+1]=t; 
		memset(G,INF,sizeof(G));
		for(i=0;i<=k+1;i++){//以旅馆为节点重新建图。 
			spfa(hotel[i]);
		}
		bfs();
	}
	return 0;
}

 

 

1、使用SQL Server 2000企业管理器和查询分析器工具(即用Transact-SQL语句)创建一个“图书读者数据库”(Book_Reader_DB); 2、使用企业管理器查看Book_Reader_DB的数据库属性,并进行修改,使之符合你的要求; 3、使用企业管理器和在查询分析器中用Transact-SQL语句的两种方法建立图书、读者和借阅三个表,其结构为: 图书(书号,类别,出版社,作者,书名,定价,备注); 读者(编号,姓名,单位,性别,电话); 借阅(书号,读者编号,借阅日期)。 要求:① 对每个属性选择合适的数据类型;② 定义每个表的主码、是否允许空值和默认值等列级数据约束;③ 对每个表的名字和表中属性的名字尽可能用英文符号标识。 4、实现相关约束:①使用企业管理器来建立上述三个表的联系,即实现:借阅表与图书表之间、借阅表与读者表之间的外码约束;② 实现读者性别只能是“男”或“女”的约束。 5、分别用企业管理器和查询分析器修改表的结构。在“图书”表中,增加两个字段,分别为“数量”和“购买日期”。在“借阅”表中增加一个“还书日期”字段。 6、用企业管理器在上述三个表中输入部分虚拟数据。 7、在查询分析器中实现基于单个表的查询 ① select * from Book ② select * from book where Bclass=’计算机’ ③ select count(*) from book group by Bclass ④ select * from Reader ⑤ select * from Borrow ⑥ select rno, count(bno) from Borrow group by rno order by rno ⑦ select bno, count(rno) from Borrow group by bno order by bno 做实验时,还可以虚拟用户的一些其它查询要求,并用Transact-SQL语句予以实现。 上述每项实验内容相应的实验步骤必须进行详细的记录,并将其整理后写在实验报告中。
Stkcd [股票代码] ShortName [股票简称] Accper [统计截止日期] Typrep [报表类型编码] Indcd [行业代码] Indnme [行业名称] Source [公告来源] F060101B [净利润现金净含量] F060101C [净利润现金净含量TTM] F060201B [营业收入现金含量] F060201C [营业收入现金含量TTM] F060301B [营业收入现金净含量] F060301C [营业收入现金净含量TTM] F060401B [营业利润现金净含量] F060401C [营业利润现金净含量TTM] F060901B [筹资活动债权人现金净流量] F060901C [筹资活动债权人现金净流量TTM] F061001B [筹资活动股东现金净流量] F061001C [筹资活动股东现金净流量TTM] F061201B [折旧摊销] F061201C [折旧摊销TTM] F061301B [公司现金流1] F061302B [公司现金流2] F061301C [公司现金流TTM1] F061302C [公司现金流TTM2] F061401B [股权现金流1] F061402B [股权现金流2] F061401C [股权现金流TTM1] F061402C [股权现金流TTM2] F061501B [公司自由现金流(原有)] F061601B [股权自由现金流(原有)] F061701B [全部现金回收率] F061801B [营运指数] F061901B [资本支出与折旧摊销比] F062001B [现金适合比率] F062101B [现金再投资比率] F062201B [现金满足投资比率] F062301B [股权自由现金流] F062401B [企业自由现金流] Indcd1 [行业代码1] Indnme1 [行业名称1] 季度数据,所有沪深北上市公司的 分别包含excel、dta数据文件格式及其说明,便于不同软件工具对数据的分析应用 数据来源:基于上市公司年报及公告数据整理,或相关证券交易所、各部委、省、市数据 数据范围:基于沪深北证上市公司 A股(主板、中小企业板、创业板、科创板等)数据整理计算
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值