codeforces 1149E Election Promises Nim遊戲

題目分析

這題好喵啊。
喵啊

如果沒有“任意修改相鄰城市的稅收”這個操作,就是個美滋滋的Nim遊戲。

接下來的思路就很巧妙了,將城市分組。所有出度爲0的點爲第0組,其他點爲第mex(其可達節點的組編號)組。

這個有兩個性質:

  1. 同一組不存在一對節點xx,yy,滿足存在邊(x,y)(x,y)
  2. 對於第tt組中的任意一個點,它可以到達第00到第tt組,每一組中的至少一點。

若每一組的異或和都爲0,則WA黨必敗,否則必勝。

第一步的策略就是,找到編號最大的,異或和不爲0的組,找到其中一個可以通過減少稅收使得改組異或和變爲0的點,通過在這個點上拉票,修改其相鄰城市的稅收,使得每一組的異或和都變爲0。

代碼

#include<bits/stdc++.h>
using namespace std;
#define RI register int
int read() {
	int q=0;char ch=' ';
	while(ch<'0'||ch>'9') ch=getchar();
	while(ch>='0'&&ch<='9') q=q*10+ch-'0',ch=getchar();
	return q;
}
const int N=200005;
int n,m,tot,cnt;
int h[N],ne[N],to[N],w[N],du[N],stk[N],seq[N],id[N],vis[N],sg[N];

void add(int x,int y) {to[++tot]=y,ne[tot]=h[x],h[x]=tot;}
void toposort() {
	int top=0,js=0;
	for(RI i=1;i<=n;++i) if(!du[i]) stk[++top]=i;
	while(top) {
		int x=stk[top];--top,seq[++js]=x;
		for(RI i=h[x];i;i=ne[i]) {
			--du[to[i]];
			if(!du[to[i]]) stk[++top]=to[i];
		}
	}
	for(RI i=n;i>=1;--i) {
		int x=seq[i];
		for(RI j=h[x];j;j=ne[j]) ++vis[id[to[j]]];
		while(vis[id[x]]) ++id[x];
		if(id[x]>cnt) cnt=id[x];
		for(RI j=h[x];j;j=ne[j]) --vis[id[to[j]]];
	}
}

int main()
{
	int x,y;
	n=read(),m=read();
	for(RI i=1;i<=n;++i) w[i]=read();
	for(RI i=1;i<=m;++i) x=read(),y=read(),add(x,y),++du[y];
	toposort();
	for(RI i=1;i<=n;++i) sg[id[i]]^=w[i];
	int flag=-1;
	for(RI i=0;i<=cnt;++i) if(sg[i]) flag=i;
	if(flag==-1) {puts("LOSE");return 0;}
	puts("WIN");
	for(RI i=1;i<=n;++i) if(id[i]==flag) {
		if((sg[id[i]]^w[i])>w[i]) continue;
		w[i]^=sg[id[i]],sg[id[i]]=0;
		for(RI j=h[i];j;j=ne[j])
			w[to[j]]^=sg[id[to[j]]],sg[id[to[j]]]=0;
	}
	for(RI i=1;i<=n;++i) printf("%d ",w[i]);
	puts("");
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章