POJ1227 RoboContest【題解報告|BFS】

題目鏈接

題目大意

題目給定一個無向圖,節點上放置有機器人,要求每一個回合機器人都要往相鄰的節點走一步,問是否存在有一個節點,使得所有機器人在某一步中能夠在此節點相會

思路分析

對於一個無向圖而言,如果我們能在第kk到達節點nn,那麼我們可以在他和相鄰節點來回穿梭,即k+2,k+4,k+6,...k+2,k+4,k+6,...這些時刻我們都可以到達這個節點。也就是說,在這道題中,我們在意的其實不是走多少步,而是步長的奇偶性。

需要注意的是,有些節點不管是奇數還是偶數都能到達。

因此,對於每一個機器人,我們只需要用BFS探索它對於每一個節點,奇數步和偶數步的到達情況,最後統計是否有節點滿足對於所有機器人都能奇數步到達或者偶數步到達,即可。

這裏我用了一個簡單的位運算的技巧,1爲奇數到達,2爲偶數到達,3爲兩者都可,那麼我們只需要把所有機器人到目標點的方法按位與即可。

TIPS:tobot的序號不一定是從1-n,有可能是0,也有可能超過n。

#define inf 0x3f3f3f3f
#define ll long long
#define vec vector<int>
#define P pair<int,int>
#define MAX 105

int T, n, k, u, v, m, a[MAX], vis[MAX], d[MAX][MAX], exi[MAX];
vec G[MAX];

int step(int k) {//從k的步數推出到相鄰節點的步數
	if (vis[k] == 1)return 2;
	else if (vis[k] == 2) return 1;
	else return 3;
}

void bfs(int k) {
	//0表示未訪問,1表示奇數步,2表示偶數步,3表示都可
	memset(vis, 0, sizeof(vis));
	memset(exi, 0, sizeof(exi));
	vis[k] = 2; queue<int> q; q.push(k); exi[k] = 1;

	while (!q.empty()) {
		int u = q.front(), s = step(u); q.pop(); exi[u] = 0;
		for (int i = 0; i < G[u].size(); i++) {
			int v = G[u][i];
			if (!vis[v]) {
				vis[v] = s;
				q.push(v);
			}
			else if (s != vis[v]) {//已經訪問過了,但是有另一種走法
				vis[v] = 3;
				if (!exi[v])
					q.push(v), exi[v] = 1;//不在隊列中則加入
			}
		}
	}

	for (int i = 0; i < MAX; i++)d[k][i] = vis[i];
}

int main() {
	scanf("%d", &T);
	while (T--) {
		scanf("%d %d", &n, &k);
		for (int i = 0; i < MAX; i++)G[i].clear();
		for (int i = 1; i <= n; i++) {
			scanf("%d %d", &u, &m);
			for (int i = 0; i < m; i++) {
				scanf("%d", &v);
				G[u].push_back(v);
			}
		}

		memset(d, 0, sizeof(d));
		for (int i = 0; i < k; i++) {
			scanf("%d", &a[i]); 
			bfs(a[i]);
		}

		int sign = 0;
		for (int i = 0; i < MAX; i++) {
			//檢查是否能都到這個節點
			int res = d[a[0]][i];
			for (int j = 1; j < k && res; j++) {
				res &= d[a[j]][i];
			}
			if (res) { sign = 1; break; }
		}
		if (sign)cout << "YES" << endl;
		else cout << "NO" << endl;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章