传送门
这题思维难度比较大_
首先,对任意集合 S S S,定义函数 f A ( S ) f_A(S) fA(S)为不管B怎样A都能进入 S S S的起点的集合, f B ( S ) f_B(S) fB(S)同理
设充电站集合为 R R R,则如果起点在 f A ( R ) f_A(R) fA(R)以外B必胜(即B一定有一种策略使得火车无法进入 R R R)
如果 f A ( R ) f_A(R) fA(R)为全集则A赢(不管怎样A总能使火车进入 R R R)
如果 f A ( R ) f_A(R) fA(R)不为全集,设 X X X为 f A ( R ) f_A(R) fA(R)的补集,则如果起点属于 X X X则B必胜
如果起点属于 f B ( X ) f_B(X) fB(X)中B一定可以进入 X X X,所以B同样必胜
剩下的节点胜负未定,我们可以抠掉这些B胜的节点,继续判断 f A ( R ) f_A(R) fA(R)是否为全集并重复上述过程,直到 f A ( R ) f_A(R) fA(R)为全集为止,此时剩下的节点就是A必胜的起点
现在问题就是快速求 f A f_A fA, f B f_B fB(由于求 f A f_A fA的过程和求 f B f_B fB的过程相似,所以这里只讨论求 f A f_A fA的方法)
由于 n ≤ 5000 n\le 5000 n≤5000,所以可以根据定义直接求 f A f_A fA
首先 f A ( S ) f_A(S) fA(S)至少是 S S S
每次选一个点,它进入 f A f_A fA的条件是:
具体实现时可以每次在 S S S中取出一个尚未取出的节点,并更新每个点是否满足条件。
举个栗子
红色节点属于A,蓝色节点属于B,黄色标记代表这是一个充电车站
首先 R = { 2 , 9 } R=\lbrace2,9\rbrace R={ 2,9}
按照前面的方法求出 f A ( R ) = { 2 , 3 , 4 , 5 , 9 } f_A(R)=\lbrace2,3,4,5,9\rbrace fA(R)={ 2,3,4,5,9}
则 X = n o t f A ( R ) = { 1 , 6 , 7 , 8 } X=notf_A(R)=\lbrace1,6,7,8\rbrace X=notfA(R)={ 1,6,7,8}
f B ( X ) = { 1 , 2 , 6 , 7 , 8 } f_B(X)=\lbrace1,2,6,7,8\rbrace fB(X)={ 1,2,6,7,8}
把 { 1 , 2 , 6 , 7 , 8 } \lbrace1,2,6,7,8\rbrace { 1,2,6,7,8}抠掉,得到 { 3 , 4 , 5 , 9 } \lbrace3,4,5,9\rbrace { 3,4,5,9}
用类似的方法,得 R = { 9 } R=\lbrace9\rbrace R={ 9}, f A ( R ) = { 3 , 4 , 5 , 9 } f_A(R)=\lbrace3,4,5,9\rbrace fA(R)={ 3,4,5,9}为全集
所以得到答案 w = { 0 , 0 , 1 , 1 , 1 , 0 , 0 , 0 , 1 } w=\lbrace0,0,1,1,1,0,0,0,1\rbrace w={ 0,0,1,1,1,0,0,0,1}
我在交的时候忘删了调试语句,结果调了好久…qwq
#include
using namespace std;
const int N=5005;
int n,m,q[N],h,t,vis[N];
vector<int> e[N],e2[N];
vector<int> f(int flag,vector<int> a,vector<int> r,vector<int> res){
memset(vis,0,sizeof(vis));
vector<int> ans(n),deg(n);
t=0,h=-1;
for(int i=0;i<n;i++)if(r[i]&&res[i])q[++h]=i,ans[i]=1;
for(int i=0;i<n;i++){
for(int j=0;j<(int)e[i].size();j++)if(res[e[i][j]]){
if(a[i]^flag)deg[i]++;else deg[i]=1;}}
while(t<=h){
int v=q[t++];
for(int i=0;i<(int)e2[v].size();i++){
int u=e2[v][i];
if(!ans[u]&&res[u]){
deg[u]--;if(!deg[u])ans[q[++h]=u]=1;}
}
}
return ans;
}
vector<int> who_wins(vector<int> a,vector<int> r,vector<int> u,vector<int> v){
n=a.size(),m=u.size();
while(m--)e[u[m]].push_back(v[m]),e2[v[m]].push_back(u[m]);
vector<int> ans(n);
for(int i=0;i<n;i++)ans[i]=1;
while(1){
int flag=1;
vector<int> res1=f(1,a,r,ans);
for(int i=0;i<n;i++)if(ans[i]&&!res1[i])flag=0;
if(flag)return ans;
for(int i=0;i<n;i++)res1[i]^=1;
vector<int> res2=f(0,a,res1,ans);
for(int i=0;i<n;i++)if(res2[i])ans[i]=0;
}
return ans;
}