CodeForces - 601A(BFS)

题目大意

有n个城市,有m对城市通火车,其他的城市间通汽车。不管是火车还是汽车,从一个城市到另一个城市的用时都为一小时。一个城市不允许同时有火车和汽车到达,但允许同时有火车和汽车发车。
问:从一号城市同时出发的火车和汽车,两者都到达n号城市的最短时间,无法到达输出 “-1”。

分析

这里有一个很有意思的事,一定有一种交通工具是直接连接一号城市和 n 号城市的
举个栗子:
4 2
1 3
3 4
这个题中只有两种状态,汽车和火车,我们用 0 和 1 表示这两种交通方式
上图:
在这里插入图片描述
很明显(1,n)没有火车直通,那么肯定是汽车直通的,现在我们就只需要找火车最短到达时间。
这就是最短路问题, 而且每条边的边权都是 1 ,直接BFS跑一遍就OK

现在有一个问题,我们如何确定是对火车路线进行BFS,还是对汽车路线进行BFS

仔细看上边的图,看到0,1我们都应该想到位运算
如果(1,n)为 0 ,是汽车直通,那么应该对火车进行BFS,火车的点都被标记为 1,也就是说需要BFS的点和(1,n)的标记是不一样的,自然的我们想到异或运算。
如果(x,y)^ (1,n)= 1, 那么(x,y)是需要进行BFS的点。
异或运算:二进制运算,简单说就是不同为 1,记住下边三个等式就OK
1 ^ 0 = 1,
1 ^ 1 = 0,
0 ^ 0 = 0

代码

#include <bits/stdc++.h>

using namespace std;

int main() {

	ios::sync_with_stdio(false);
	
	int n, m;
   	cin >> n >> m;
    	int x, y;
    	for (int i = 1; i <= m; i++) {
        	cin >> x >> y;
        	ma[x][y] = ma[y][x] = 1;
    	}

	queue<int>q;
	
	q.push(1);       // 从一号点出发 
   	memset(d, -1, sizeof(d)); //初始 1 号点到各点的距离为 -1
  	d[1] = 0;
 	bool flag = true;
 	while(!q.empty()){
       		int v = q.front();
       		q.pop();
		
		if(v == n){   // 因为边权都为 1,所以,第一次到达 n号节点时,一定是用时最短的 
	       		cout << d[n] << endl;
	        	flag = false;
	         	break;
	        }
		for(int i = 1; i <= n; i++){  //与 v 点连接的点就是下一步可以到达的点 
		         if(ma[v][i] ^ ma[1][n]){  // 异或运算判断要走火车还是汽车 
		         	if(d[i] == -1){       // 没有到过的点加入队列中,到过的点不需要重复判断,一定是费时的 
		                	q.push(i);
		                	d[i] = d[v] + 1;
		            	}
		        }
		}
	}
	if(flag) cout << -1 << endl;  // 如果不能跑到(1,n)那就是 -1 了 
    
    return 0;
}

本来一直以为这个题要用 Dijkstra 算法写,后来发现因为边权值都为1,直接BFS就OK
哪里我说的不清楚的,欢迎留言提问

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值