题解 P5767 【[NOI1997]最优乘车】

题目

核心思路:Dijkstra算法


首先,我认为这道题最重要的是建图,解释一下我是如何建图:

(题目中说明了是“单程巴士线路”,故图为有向图。)

样例:
题解 P5767 【[NOI1997]最优乘车】_第1张图片

(线路的站点就是节点,边上的数字就是指这条边属于哪一条线路)

由样例图可以看出,1->7的最少换乘的次数是2次:

1->3 换乘 3->6 换乘 6->7

但如果只是单纯的作模拟,这道题就失去了意义。

我们不妨这样建图:

将每一条线路的站点,都与这条线路的起点相连。

题解 P5767 【[NOI1997]最优乘车】_第2张图片

在同一条线路上的节点,对于最后的换乘数是没有贡献的。 也就是说,同一条线路上的点是等价的。

而将每个点都与起点相连,是因为不能确定后来读入的线路是否与先前的线路存在换乘点。 所以干脆就全连上。

这样一来,图中1->n的最短路,就是最小换乘数+1。


然后,讲这道题如何读入。

我看已有的许多的题解中,是用字符串读入的。大可不必。

我们可以利用空格换行符来读入。

像这样:

while(c!=-1 && c!='\r')	//'\n'
{
	scanf("%d",&a[ ++n ]);
	c=-1;
	scanf("%c",&c);
}

(这个'/r'和洛谷的测评姬有关)


难度评分:建议绿题

理由:这题在Dijkstra模板题的基础上,增加了对Dijkstra的理解应用,同时这道题卡读入。

附上代码:

#include 
#define MAXN 510
#define MAX 0x3f3f3f3f
using namespace std;
int ori=1,node;	//ori 起点   node 节点数 
int a[5005];	//存输入 
int dis[MAXN],g[MAXN][MAXN];
bool vis[MAXN]; 
void init()			//初始化 
{
	memset(vis,0,sizeof(vis));
	memset(dis,0,sizeof(dis));
	vis[ori]=1;
	for(int i=1;i<=node;++i)		dis[i] = (i == ori ? 0 : g[ori][i]);
}
void Dijkstra()		//朴素Dijkstra 
{
	int k;	init();
	for(int i=1;i<=node-2;++i)
	{
		int m=MAX;
		for(int j=1;j<=node;++j)
		{
			if(dis[j]=MAX) printf("NO");
    	else printf("%d",dis[node]-1);	//换乘数为最短距离-1 
	return 0;
}

你可能感兴趣的:(题解 P5767 【[NOI1997]最优乘车】)