CCCC天梯赛 L3-014. 周游世界

本质是个dijkstra的裸题,但是特别的烦。。。。

由于图很复杂,所以不要一开始就将所有可相互到达的点连边,而是在dijkstra跑的时候,查询bus路线,再连边。

然后压入优先队列的时候,以及弹出的时候,要判断下是否比当前最优解差,是的话就continue。

因为要输出路径,所以还要存from节点。

总之,特别的烦。。。

#include <bits/stdc++.h>
using namespace std;

const int MAXN=10010;
const int MAXM=110;
int s[MAXM][MAXM];
int dis[MAXN],cha[MAXN],from[MAXN],take[MAXN],ansfrom[MAXN],ansto[MAXN],ansbus[MAXN];
vector<int> can_bus[MAXN],stop_num[MAXN];

struct node
{
	int x,dis,cha,from,take;
	bool friend operator <(node n1,node n2)
	{
		if(n1.dis!=n2.dis)
			return n1.dis>n2.dis;
		return n1.cha>n2.cha;
	}
}now,son;
priority_queue <node> q;

int main()
{
	int n,i,j,qnum,st,ed,busindex,stopindex,ansdis,chanum,nowx;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		scanf("%d",&s[i][0]);
		for(j=1;j<=s[i][0];j++)
		{
			scanf("%d",&s[i][j]);
			can_bus[s[i][j]].push_back(i);
			stop_num[s[i][j]].push_back(j);
		}
	} 
	scanf("%d",&qnum);
	while(qnum--)
	{
		scanf("%d%d",&st,&ed);
		memset(dis,-1,sizeof(dis));
		while(!q.empty())
			q.pop();
		now.x=st; now.dis=0; now.cha=0; now.from=-1; now.take=-1;
		q.push(now);
		ansdis=-1;
		while(!q.empty())
		{
			now=q.top();
			q.pop();\
			if(dis[now.x]!=-1&&dis[now.x]<now.dis||(dis[now.x]==now.dis&&cha[now.x]<now.cha))
				continue;
			dis[now.x]=now.dis;
			cha[now.x]=now.cha;
			from[now.x]=now.from;
			take[now.x]=now.take;
			if(now.x==ed)
			{
				ansdis=now.dis;
				break;
			}
			for(i=0;i<can_bus[now.x].size();i++)
			{
				busindex=can_bus[now.x][i];
				stopindex=stop_num[now.x][i];
				for(j=1;j<=s[busindex][0];j++)
				{
					son.x=s[busindex][j];
					son.dis=now.dis+abs(stopindex-j);
					son.cha=now.cha+1;
					son.from=now.x;
					son.take=busindex;
					if(dis[son.x]!=-1&&dis[son.x]<son.dis||(dis[son.x]==son.dis&&cha[son.x]<son.cha))
						continue;
					dis[son.x]=son.dis;
					cha[son.x]=son.cha;
					q.push(son);
				}
			}
		}
		if(ansdis!=-1)
		{
			chanum=0;
			nowx=ed;
			while(nowx!=-1)
			{
				ansto[chanum]=nowx;
				ansfrom[chanum]=from[nowx];
				ansbus[chanum]=take[nowx];
				nowx=from[nowx];
				chanum++;
			} 
			printf("%d\n",ansdis);
			for(i=chanum-2;i>=0;i--)
			{
				printf("Go by the line of company #%d from %04d to %04d.\n",ansbus[i],ansfrom[i],ansto[i]);
			}
		}
		else
			printf("Sorry, no line is available.\n");
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值