其他分享
首页 > 其他分享> > ABC 209 E - Shiritori

ABC 209 E - Shiritori

作者:互联网

E - Shiritori

对抗博弈,BFS,哈希

  1. 对于每个字符串,设前三位哈希值为 a,后三位哈希值为 b,则可用 b 来代表该字符串,连一条 a -> b 表示若当前是 a 字符串,可以变成 b

  2. 反向建图,连 b -> a 的边,则入度为 0 的边就是原图的终点,是必败态,赋 0,并将其放入队列

  3. bfs 过程中,有如下性质

    1. 必败态 b 的下一个点 a 是必胜态(若当前在 a 点,可选择走到 b 点,对手必败)
    2. 必胜态 b 的下一个点 a,若 a 的入度为 0,则 a 是必败态(若当前在 a 点,入度为 0 说明 a 只能往 b 走,所以对手必胜); 若 a 的入度不为 0,则 a 并不能确定状态(当前在 a 的这个人肯定不愿走到 b 让对手必胜,所以要等别的选择)
    3. 已经放入队列的点表示这个点的状态已经确定了
  4. 类似拓扑排序,每次搜到一个点要将它的入度减 1

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <map>
#include <queue>
using namespace std;
#define endl "\n"
 
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5 + 10;
int din[N], id[N], ans[N];
int n;
 
int f(char x)
{
	if (x >= 'a' && x <= 'z')
		return x - 'a';
	return x - 'A' + 26;
}
int hs(string s)
{
	return f(s[0]) * 52 * 52 + f(s[1]) * 52 + f(s[2]);
}
 
vector<vector<int> > G(N);
 
void add(int u, int v)
{
	G[u].push_back(v);
	din[v]++;
}
 
void bfs()
{
	queue<int> q;
	for (int i = 0; i < N; i++)
	{
		if (!din[i])
		{
			ans[i] = 0;
			q.push(i);
		}
	}
	while(!q.empty())
	{
		int u = q.front();
		q.pop();
		for (auto v : G[u])
		{
			if (ans[v] == -1)
			{
				din[v]--;
				if (ans[u] == 0)
				{
					ans[v] = 1;
					q.push(v);
				}
				else if (din[v] == 0)
				{
					ans[v] = 0;
					q.push(v);
				}
			}
		}
	}
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		string s;
		cin >> s;
		int u = hs(s.substr(0, 3)), v = hs(s.substr(s.size() - 3));
		add(v, u);
		id[i] = v;
	}
	memset(ans, -1, sizeof ans);
	bfs();
	for (int i = 1; i <= n; i++)
	{
		int u = id[i];
		if (ans[u] == 1)
			cout << "Aoki" << endl;
		else if (ans[u] == 0)
			cout << "Takahashi" << endl;
		else
			cout << "Draw" << endl;
	}
    return 0;
}

标签:Shiritori,din,ABC,209,入度,int,ans,push,include
来源: https://www.cnblogs.com/hzy717zsy/p/16356747.html