gym102220 Mini-game Before Contest

https://codeforces.com/gym/102220/problem/F

在vj跟着现场榜打的,没人开这题,水题啊卧槽,一直在想A题,A题难得一比卧槽,省赛还是要多开题,cf上gym牛逼网友F过了一车。虽然我当时看了这题但是因为没人过所以没有花很多时间想,晚上仔细想想一写就过了

用-1表示平局,0表示A获胜,1表示B获胜,b[i]=0/1表示他实际是希望谁赢的,dp[i][j]表示到了第i个点现在是第j个人移动时的状态

从没有出度的点开始,此时dp[i][1-6]是谁获胜了都知道了,就是当前移动的输了,接着吧他们放到队列里,队列里存新增的被确定为0或者1的dp[u][i],从队列里拿出一个u,i,然后枚举所有连向u的点v,及存在v->u的一条正向边,v可以走到u,如果dp[u][i]正如pre(i)所愿,dp[u][i]=b[pre(i)],那么直接把dp[v][pre(i)]确定,加进队列,否则如果与pre(i)期望相反,那么我们知道如果v能走到的所有点都与pre(i)期望相反,那么dp[v][pre(i)]才是必输的,否则他可以选择走某一个点得到平局,用一个du[v][pre(i)]来记录一下是不是全都必输了就行。

我们发现每一个dp[u][i]不等于-1也就是有确定的胜负之后,只会被加入队列一次,而且更新也只会更新一次,所以虽然是类似spfa的写法,但实际上只有O((n+m)*6)的复杂度

我好菜啊.jpg,以后一定要每道题都认真想想,不能比赛后期看没人过就摸鱼啊

#include<bits/stdc++.h>
using namespace std;

const int maxl=2e5+10;

int n,m;
int a[10],b[10];
int dp[maxl][7],du[maxl][7];
char ord[10],s[10];
typedef pair<int,int> p;
vector<int> e[maxl],fe[maxl];
queue<p> q;
bool in[maxl][7];

inline void prework()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=6;j++)
			dp[i][j]=-1,du[i][j]=0,in[i][j]=false;
		e[i].clear();
		fe[i].clear();
	}
	int u,v;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&u,&v);
		e[u].push_back(v);
		fe[v].push_back(u);
		for(int j=1;j<=6;j++)
			du[u][j]++;
	}
	scanf("%s",ord+1);
	scanf("%s",s+1);
	for(int i=1;i<=6;i++)
		a[i]=s[i]-'0',b[i]=(ord[i]-'A')^a[i];
}

inline int pre(int i)
{
	if(i==1)
		return 6;
	return i-1;
}
inline int nxt(int i)
{
	if(i==6)
		return 1;
	return i+1;
}

inline void mainwork()
{
	while(!q.empty()) q.pop();
	for(int i=1;i<=n;i++)
	if(du[i][1]==0)
	{
		for(int j=1;j<=6;j++)
		if(ord[j]=='A')
		{	
			dp[i][j]=1; //A can't move B win
			q.push({i,j});in[i][j]=true;
		}
		else 
		{
			dp[i][j]=0;//0 -> A win
			q.push({i,j});in[i][j]=true;
		}
	}
	int u,i;p d;
	while(!q.empty())
	{
		d=q.front();q.pop();
		u=d.first;i=d.second;
		for(int v:fe[u])
		if(dp[v][pre(i)]==-1)
		{
			if(dp[u][i]==b[pre(i)])
			{
				dp[v][pre(i)]=b[pre(i)];
				q.push({v,pre(i)});in[v][pre(i)]=true;
			}
			else
			{
				du[v][pre(i)]--;
				if(du[v][pre(i)]==0)
				{
					dp[v][pre(i)]=b[pre(i)]^1;
					q.push({v,pre(i)});in[v][pre(i)]=true;
				}
			}
		}
	}
}

inline void print()
{
	for(int i=1;i<=n;i++)
	if(dp[i][1]<0)
		putchar('D');
	else 
		putchar('A'+dp[i][1]);
	puts("");
}

int main()
{
	int t;
	scanf("%d",&t);
	for(int i=1;i<=t;i++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/109108921
今日推荐