2024/2/15

补题

codeforce925 F F - Chat Screenshots

题意:

给定一个队列,n个人,每个人的视角是把自己放在最前面,剩下按照原来顺序。现在给你m个视角,问你是否合法。

思路:

我们可以先假设每个队列都是合法的,然后找到矛盾就行了。

但是每个人都会把自己放在最前面,所以我们不用管第一个。剩下的记录前后位置,用有向图存储。矛盾就是有向图出现回路。

问题1:怎么得到有向图?

有向图之前我习惯用vector的邻接矩阵,但是这个题会有重复的点记录,所以用set[]更好。

问题2:怎么判断有向图是否有回路?
有两种办法:

(1)拓扑排序,两个步骤,入度为零的点压入队列,把队列中的点邻边删除,重复这两个步骤,还有剩余的点就是环

(2)dfs和bfs,这两个是搜索,需要一个状态数组,状态数组需要记录三个状态(搜索完,正在搜索,没有搜索),如果两个正在搜索的点相遇,那就是出现环。

拓扑

#include <bits/stdc++.h>
using namespace std;
	
#define int long long
set<int> adj[200005];
int in[200005] = {0};

void solve() {

	int n, m;
	cin >> n >> m;

	for (int i = 1; i <= n; i++) {
		adj[i].clear();
		in[i] = 0;
	}
	
	for (int i = 0; i < m; i++) {
		int la, t;
		cin >> la;

		for (int i = 0; i < n - 1; i++) {
			cin >> t;
			if(i && adj[la].find(t) == adj[la].end() ) {
				adj[la].insert(t);
				in[t]++;
			}
			la = t;
		}
	}
	
	queue<int>q;
	int cnt = 0;

	for (int i = 1; i <= n; i++) {
		if(in[i] == 0) {
			q.push(i);
			cnt++;
		}
	}

	while(q.size()) {
		int x = q.front();
		q.pop();

		for (auto it : adj[x]) {
			if(--in[it] == 0) {
				q.push(it);
				cnt++;
			}
		}
	}

	if(cnt == n) {
		cout << "YES\n";
	}
	else {
		cout << "NO\n";
	}
}

signed  main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);

	int T = 1;
	cin >> T;

	while(T--) {
		solve();
	}

	return 0;
}

dfs

#include <bits/stdc++.h>
using namespace std;
	
#define int long long
set<int> adj[200005];
int state[200005];
bool ok = 1;
//0-no 1-ing 2-ok

bool dfs(int x) {
	for (auto it : adj[x]) {
		if(state[it] == 0) {
			state[it] = 1;
			if(!dfs(it)) {
				return 0;
			}
			state[it] = 2;
		}
		else if(state[it] == 1) {
			ok = 0;
			return 0;
		}
	}
	return 1;
}

void solve() {
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		adj[i].clear();
		state[i] = 0;
	}
	
	for (int i = 0; i < m; i++) {
		int la, t;
		cin >> la;

		for (int i = 0; i < n - 1; i++) {
			cin >> t;
			if(i && adj[la].find(t) == adj[la].end() ) {
				adj[la].insert(t);
			}
			la = t;
		}
	}
	
	ok = 1;
	for (int i = 1; ok && i <= n; i++) {
		if(!state[i]) {
			dfs(i);
		}
	}

	if(ok) {
		cout << "YES\n";
	}
	else {
		cout << "NO\n";
	}
}

signed  main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);

	int T = 1;
	cin >> T;

	while(T--) {
		solve();
	}

	return 0;
}
posted @ 2024-02-15 00:29  contiguous  阅读(14)  评论(0编辑  收藏  举报