首页 > 试题广场 >

公交车

[编程题]公交车
  • 热度指数:1974 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
一座城市有 n 个公交站台,站点从 1 到 n 编号,和 m 班公交车,公交车从 1 到 m 编号,乘坐每班公交车只需花费 1 元钱,第 i 班公交车一共经过 ti 个站点,分别为站点 ai,1,ai,2,...,ai,ti,小明可以乘坐第 i 班公交车从这 ti  个站台中的任意一个到达任意一个站点,如一班公交车经过站点 1,2,3,那么小明花费 1 元钱就可以从 1 到 2 ,从 1 到 3 ,从 2 到 1,从 3 到 1,从3 到 2。
小明想从 1 号站台到 n 号站台,问他最少花费多少钱。

数据范围:

输入描述:
第一行两个数 n , m。
接下来 m 行,依次描述公交车经过的站点,第 i 行开头一个数 t_i ,表示第 i 班公交车经过的站点数,接下来的 t_i 个数,依次表示这 t_i 个站点。



输出描述:
输出一个数,从 1 号站点到 n 号站点的最小代价,如果不能达到则输出 -1。

示例1

输入

5 3
3 1 2 3
3 3 4 2
3 3 5 4

输出

2

说明

先坐第一班公交车从 1 号到 3 号站点,再坐第三班公交车从 3 号站点到 5 号站点。
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

/**
 * @author wylu
 */
public class Main {
    static ArrayList<Integer>[] graph;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] strs = br.readLine().split(" ");
        int n = Integer.parseInt(strs[0]), m = Integer.parseInt(strs[1]);
        graph = new ArrayList[n + m + 1];

        //建图, 将公交车抽象成一个站点, 只记录公交车到相应站点的边
        for (int i = 1; i <= m; i++) {
            strs = br.readLine().split(" ");
            graph[i + n] = new ArrayList<>();
            for (int j = 1; j < strs.length; j++) {
                int station = Integer.parseInt(strs[j]);
                if (graph[station] == null) graph[station] = new ArrayList<>();
                graph[station].add(i + n);
                graph[i + n].add(station);
            }
        }

        //bfs求最短路, 
        int res = bfs(1, n, m);
        //因为设立了抽象点,起点距离又设为1,所以每个点的距离是实际距离的两倍加一
        System.out.println(res == 0 ? "-1" : res / 2);
    }

    private static int bfs(int x, int n, int m) {
        int[] dist = new int[n + m + 1];
        LinkedList<Integer> queue = new LinkedList<>();
        dist[x] = 1;
        queue.offer(x);
        while (!queue.isEmpty()) {
            int cur = queue.poll();
            for (Integer e : graph[cur]) {
                if (dist[e] == 0) {
                    dist[e] = dist[cur] + 1;
                    queue.offer(e);
                }
            }
        }
        return dist[n];
    }
}

编辑于 2019-03-12 17:11:12 回复(0)
思路:对于每个公交线路创建一个虚拟点,连接这条线路的所有点。对构造的图求1-n最短路,距离/2即为答案(因为多了到虚拟点的距离

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std ;
typedef pair<int,int>P ; 
const int AX = 1e5 + 666 ; 
struct Node{
	int v , w , nxt ;
	Node(){}
	Node( int v , int w , int nxt ):v(v),w(w),nxt(nxt){}
}G[AX<<1] ; 
int tot ; 
int head[AX] ; 
int vis[AX] ; 
int dis[AX] ; 
int n , m ;
void add( int u , int v , int w ){
	G[tot] = Node( v , w , head[u] ) ; head[u] = tot ++  ;
	G[tot] = Node( u , w , head[v] ) ; head[v] = tot ++  ; 
}
void djistra(){
	memset( dis , 0x3f , sizeof(dis) ) ; 
	priority_queue<P , vector<P> , greater<P> > q ;
	q.push(P(0,1)) ; 
	dis[1] = 0 ; 
	while( !q.empty() ){
		P tmp = q.top() ; 
		q.pop() ; 
		int u = tmp.second ; 
		int w = tmp.first ; 
		vis[u] = 1 ; 
		for( int i = head[u] ; ~i ; i = G[i].nxt ){
			int v = G[i].v ; 
			if( !vis[v] && dis[v] > dis[u] + G[i].w ){
				dis[v] = dis[u] + G[i].w ; 
				q.push( P( dis[v] , v ) ) ;
			}
		}
	}
}
int main(){
	int x , y ; 
	memset( head , -1 , sizeof(head) ) ;
	memset( vis , 0 , sizeof(vis) ) ; 
	scanf("%d%d",&n,&m); 
	for( int i = 1 ; i <= m ; i++ ){
		scanf("%d",&x);
		while( x-- ){
			scanf("%d",&y);
			add( y , n + i , 1 );
		}
	}
	djistra();
	printf("%d\n",( dis[n] == INF ? -1 : dis[n] / 2 ) );
	return 0 ; 
}


编辑于 2020-04-18 18:42:25 回复(1)
#include <bits/stdc++.h>

using namespace std;

vector<int> Adj[200003];
int d[200003];

int BFS(int s, int e)
{     queue<int> q;     q.push(s);     d[1] = 1;     while(!q.empty())     {         int p = q.front();         q.pop();         for(int i=0;i<Adj[p].size();i++)         {             if(d[Adj[p][i]]==0)             {                 d[Adj[p][i]] = d[p] + 1;                 q.push(Adj[p][i]);             }         }     }     if(d[e]==0)         return -1;     else         return d[e]/2;     }

int main()
{     int n,m;     while(cin>>n>>m)     {         int t,u,v;         for(int i=1;i<=m;i++)         {             cin>>t;             for(int j=1;j<=t;j++)             {                 cin>>u;                 Adj[u].push_back(i+100000);                 Adj[i+100000].push_back(u);             }         }         cout<<BFS(1,n)<<endl;     }     return 0;
}

发表于 2019-01-21 22:14:01 回复(1)

原来有n个公交车站,有m条公交线路。对于其中一条线路a->b->c,使得a,b,c三个公交车站距离变成了1(1块钱可以到达)。因此,我们建立无向图(边全值为1)。但是公交线路长度很长(2<=t <=100000),这样对一个公交线路来说,建边复杂度为。为了降低复杂度,每个线路都建立一个虚拟节点,使得公交车站通过虚拟节点相连接,这样就减少了边的数量,这样对一个公交线路来说,建边复杂度为。对于对于其中一条线路a->b->c, 建立一个节点x,如果要求a到b的距离,a,b之间并没有直接边相连,而是通过x节点,间接相连(a->x->b)。因此,我们将边的权值设为0.5,a到b的权值就仍然为1。问题还是求1-n的距离。

import java.util.*;
public class Main {
    static int bfs(List<Integer>[] g, int n){
        boolean[] used = new boolean[g.length];
        LinkedList<Integer> q = new LinkedList<>();
        q.offer(1); used[1] = true;
        int distance = 0;
        while(!q.isEmpty()){
            int size = q.size();
            distance ++;
            for(int i=0; i < size; i++) {
                int cur = q.poll();
                for(int j=0; j <g[cur].size(); j++) {
                    int v = g[cur].get(j);
                    if(v == n) return distance/2;
                    if(used[v] == false) {
                        used[v] = true;
                        q.offer(v);
                    }
                }
            }
        }
        return -1;
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), m = sc.nextInt();
        List[] g = new ArrayList[n+m+1];
        for(int i=1; i < g.length; i++) g[i] = new ArrayList<Integer>();
        for(int i=1; i <= m; i++) {
            int t = sc.nextInt();
            for(int j=1; j <= t; j++) {
                int v = sc.nextInt();
                g[n+i].add(v);
                g[v].add(n+i);
            }
        }
        int res = bfs(g, n);
        System.out.println(res);
    }
}
发表于 2020-07-01 12:25:07 回复(5)
n,m = list(map(int,input().split()))
edges = []
for _ in range(m):
    t = list(map(int,input().split()))
    for i in range(1,t[0]):
        for j in range(i+1,t[0]+1):
            edges.append([t[i],t[j]])
adjacent = {}
for index in range(1,n+1):
    adjacent[index] = []
for i in range(len(edges)):
    if edges[i][1] not in adjacent[edges[i][0]]:
        adjacent[edges[i][0]].append(edges[i][1])
    if edges[i][0] not in adjacent[edges[i][1]]:
        adjacent[edges[i][1]].append(edges[i][0])

def bfs(route,cost):
    flag = True
    if route[-1] == 5:
        project.append(cost)
        flag = False
    if flag:
        for next_station in adjacent[route[-1]]:
            if next_station not in route:
                bfs(route+[next_station],cost+1)

project = []
route = [1]
cost = 0
bfs(route,cost)
print(min(project))
10%,哭了
发表于 2019-09-07 13:36:01 回复(0)
这题目也是醉了. 这空间..唉.. 
发表于 2019-05-23 22:41:16 回复(0)
动态规划
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
public class Main {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner s=new Scanner(System.in);
        int z=s.nextInt();
        int bn=s.nextInt();
        int[] an=new int[z];
        List<Set<Integer>> cunList=new ArrayList<Set<Integer>>();
        for (int i = 0; i < z; i++) {
            an[i]=200000;
        }
        for (int i = 0; i < bn; i++) {
            int flag=0;
            Set<Integer> temp=new TreeSet<Integer>();
            int m1=s.nextInt();
            for (int j = 0; j < m1; j++) {
                int t1=s.nextInt();
                temp.add(t1);
                if (t1==1) {
                    flag=1;
                }
            }
            if (flag==1) {
                for (Integer integer : temp) {
                    an[integer-1]=1;
                }
            }else {
                cunList.add(temp);
            }
        }
        int min=200000;
        for (Set<Integer> set : cunList) {
            min=200000;
            for (Integer zz : set) {   //遍历对比该车每一站                          
            if (an[zz-1]!=200000&&an[zz-1]<min) {
                min=an[zz-1];
            }    
            }
            for (Integer zz : set) {
                if ((min+1)<an[zz-1]) {
                    an[zz-1]=min+1;
                }
            }
        }
        if (an[z-1]<200000) {
            System.out.println(an[z-1]);
        }else {
            System.out.println(-1);
        }
    }
}
 

发表于 2019-01-16 15:36:11 回复(0)