zoukankan      html  css  js  c++  java
  • 题解 P5767 【[NOI1997]最优乘车】

    题目

    核心思路:Dijkstra算法


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

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

    样例:
    aVaHTe.png

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

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

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

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

    我们不妨这样建图:

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

    aVaqFH.png

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

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

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


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

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

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

    像这样:

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

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


    难度评分:建议绿题

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

    附上代码:

    #include <bits/stdc++.h>
    #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]<m && vis[j]==0)
    			{m=dis[j];	k=j;}
    		}
    		if(m==MAX)		break;
    		vis[k]=1;
    		for(int j=1;j<=node;++j)
    			if(dis[k]+g[k][j]<dis[j])
    				dis[j]=dis[k]+g[k][j];	
    	}
    	return ;
    }
    int main()
    {
    	int edge;
    	scanf("%d%d",&edge,&node);
    	for(int i=1;i<=node;++i)
    		for(int j=1;j<=node;++j)
    			g[i][j]=MAX;
    	for(int i=1;i<=edge;++i)
    	{
    		memset(a,0,sizeof(a));
    		int n=0;				//计数器 
    		char c=1;
    		while(c!=-1 && c!='
    ')	//'
    '
    		{
    			scanf("%d",&a[ ++n ]);
    			c=-1;
    			scanf("%c",&c);
    		}
    		for(int j=1;j<n;++j)
    			for(int k=j+1;k<=n;++k)
    				g[ a[j] ][ a[k] ]=1;
    	}
    	Dijkstra();
    	if(dis[node]>=MAX) printf("NO");
        	else printf("%d",dis[node]-1);	//换乘数为最短距离-1 
    	return 0;
    }
    
  • 相关阅读:
    为什么项目经理非常难有节操的选举
    二叉查找树的删除操作
    二叉查找树的前驱后继
    替罪羊树
    树链剖分
    DFS序
    bzoj3224: Tyvj 1728 普通平衡树(平衡树)
    splay树入门(带3个例题)
    红黑树
    AVL树
  • 原文地址:https://www.cnblogs.com/cyl-oi-miracle/p/13394742.html
Copyright © 2011-2022 走看看