首页 > 其他分享 >luogu P1971 [NOI2011] 兔兔与蛋蛋游戏

luogu P1971 [NOI2011] 兔兔与蛋蛋游戏

时间:2023-01-09 19:36:02浏览次数:67  
标签:int luogu 兔兔 必胜 NOI2011 using con Fl define

题面传送门

没想到二分图博弈这么早就考了?

首先我们发现,如果将和起点行列之和奇偶性一样的点设为黑色,其余设为白色,那么每次空格只会在异色边之间走,而不会在同色边之间走。

这就类似于一个二分图,更具体的,如果一个黑色方格上面的棋子是X(认为起点也是X),一个白色放个上面的棋子是O,且两者相邻,则两者之间有一条边。双方只能每次走一条边,且走过的点不能再走。二分图博弈的结论是:对于某个点,删掉这个点以后如果和没删掉之前最大匹配数不一样,则先手必胜,否则后手必胜。

考虑如何证明。首先,这个条件相当于如果起点一定在最大匹配中,那么必胜。考虑一个一定在最大匹配中的点,这表明这个点所延伸出的交错路中,至少有一条长度为奇数。则先手可以向这条路走,则先手可必胜。

对于这道题来说只需倒着加点,每次在残量网络上增广即可。时间复杂度\(O(knm)\)

code:

#include<bits/stdc++.h>
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((m)*(x-1)+(y))
#define R(n) (rnd()%(n))
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using ll=long long;using db=double;using lb=long db;using ui=unsigned;using ull=unsigned ll;
using namespace std;const int N=2e3+5,M=N*N*2+5,K=1e5+5,mod=998244353,Mod=mod-1;const ll INF=2e18+7;const db eps=1e-5;mt19937 rnd(time(0));
int n,m,k,x,y,X[N],Y[N],A[N][N],Fl[N][N],W[N],Ans[N],Ah,S,T;char c[N];
int xp[4]={1,0,-1,0},yp[4]={0,1,0,-1};
struct yyy{int to,w,z;};struct ljb{int head=1,h[N];yyy f[M];void add(int x,int y,int z){f[++head]=(yyy){y,z,h[x]};h[x]=head;}}s;
void con(int x,int y,int z){/*cerr<<x<<' '<<y<<'\n';*/s.add(x,y,z);s.add(y,x,0);}
namespace Dicnic{
	int d[N],Ns[N];queue<int> Q;
	int BFS(){
		while(!Q.empty()) Q.pop();Me(d,0x3f);d[S]=0;Q.push(S);Ns[S]=s.h[S];while(!Q.empty()){
			int x=Q.front();/*cerr<<x<<'\n';*/Q.pop();yyy tmp;for(int i=s.h[x];i;i=tmp.z){
				tmp=s.f[i];if(!tmp.w||d[tmp.to]<=d[x]+1) continue;d[tmp.to]=d[x]+1;Q.push(tmp.to);Ns[tmp.to]=s.h[tmp.to];
				if(tmp.to==T) return 1;
			}
		}return 0;
	}
	int DFS(int x,int Sum){
		if(x==T) return Sum;int i,k,pus=0;yyy tmp;for(int i=Ns[x];i;i=tmp.z){
			tmp=s.f[i];Ns[x]=i;if(!tmp.w||d[tmp.to]!=d[x]+1) continue;k=DFS(tmp.to,min(tmp.w,Sum));if(!k) d[tmp.to]=1e9;
			s.f[i].w-=k;s.f[i^1].w+=k;pus+=k;Sum-=k;if(!Sum) break;
		}return pus;
	} 
	int calc(){int Ans=0;while(BFS()) Ans+=DFS(S,1e9);/*cerr<<'\n';*/return Ans;}
}
int main(){
	freopen("1.in","r",stdin);
	int i,j,h;scanf("%d%d",&n,&m);T=n*m+1;for(i=1;i<=n;i++) for(scanf("%s",c+1),j=1;j<=m;j++) c[j]^'.'?(A[i][j]=(c[j]=='O')):(X[0]=i,Y[0]=j);
	scanf("%d",&k);for(i=1;i<=2*k;i++) scanf("%d%d",&X[i],&Y[i]),Fl[X[i]][Y[i]]=1;Fl[X[0]][Y[0]]=1;
	for(i=1;i<=n;i++){
		for(j=1;j<=m;j++) if(!Fl[i][j]){
			if((i+j-X[0]-Y[0])&1)con(d(i,j),T,1);else {
				con(S,d(i,j),1);if(!A[i][j])for(h=0;h<4;h++) {
					int x=i+xp[h],y=j+yp[h];if(x<1||y<1||x>n||y>m||Fl[x][y]||!A[x][y]) continue;
					con(d(i,j),d(x,y),1);
				}
			}
		}
	}
	for(i=2*k;~i;i--){
		if(i&1) {
			con(d(X[i],Y[i]),T,1);if(A[X[i]][Y[i]])for(h=0;h<4;h++){
				x=X[i]+xp[h],y=Y[i]+yp[h];if(x<1||y<1||x>n||y>m||Fl[x][y]||A[x][y]) continue;
				con(d(x,y),d(X[i],Y[i]),1);	
			}
		}else{
			con(S,d(X[i],Y[i]),1);if(!A[X[i]][Y[i]])for(h=0;h<4;h++) {
				int x=X[i]+xp[h],y=Y[i]+yp[h];if(x<1||y<1||x>n||y>m||Fl[x][y]||!A[x][y]) continue;
				con(d(X[i],Y[i]),d(x,y),1);
			}
		}Fl[X[i]][Y[i]]=0;
		Ans[i]=Ans[i+1]+Dicnic::calc();
	}
	for(i=1;i<=k;i++) Ans[2*i-2]^Ans[2*i-1]&&Ans[2*i-1]^Ans[2*i]&&(Ans[++Ah]=i);printf("%d\n",Ah);for(i=1;i<=Ah;i++) printf("%d\n",Ans[i]);
}

标签:int,luogu,兔兔,必胜,NOI2011,using,con,Fl,define
From: https://www.cnblogs.com/275307894a/p/17038336.html

相关文章

  • Luogu P4592 [TJOI2018]异或 做题记录
    随机跳的。树上维护序列,显然树剖。维护异或,显然01trie。01trie维护区间异或,显然可持久化一下。看到时限很大,显然可以双log。于是跑一边树剖,再根据id暴力建一个可......
  • luogu P5037 抓捕
    ##题意有$n$个点的图,任意一点$x$到可去另外一点$y$必须互质,即$\gcd(x,y)=1$。图无边权,但是拥有点权。求到终点$en$的最短距离。---##思路此题需使用Dijks......
  • Luogu P4591 [TJOI2018] 碱基序列
    链接难度:\(\texttt{省选/NOI-}\)有\(k\)组,每一组有\(a_i\)个字符串\(t_{k,a_i}\),询问分别在每一组选一个字符串拼成的字符串在文本串\(s\)出现的个数的所有情况......
  • 题解: Luogu P8894 「UOI-R1」求和
    题目链接:link前言我的一个学长在一次比赛中出了这道题,然后,我就把这道题切了其实这道题还是比较简单的,然后我就介绍一下我的比赛时的思路和做法30分做法根据标签我......
  • Luogu P2082 区间覆盖(加强版)
    链接难度:普及/提高-有\(n\)个区间\([s_i,t_i]\),求被这\(n\)个区间覆盖的长度。数据范围:\(n\le10^5,1\les_i<t_i\le10^17\)。把每个区间都换成一组匹配的括......
  • luogu P2757 [国家集训队]等差子序列
    Link题解降智了。。。首先我们不需要关心\(Len\)是多少,只需要找到长度为\(3\)的等差子序列就行了。然后就枚举中点\(mid\),看看存不存在\(l<mid<r\)使得\(a_{mi......
  • 题解 : Luogu P2197 【模板】nim 游戏
    题目链接:link结论如果$a_1\oplusa_2\oplus...\oplusa_n\not=0$,则先手必胜证明操作到最后时,每堆石子数都是\(0\),\(0\oplus0\oplus...\oplus0=0......
  • Luogu P4178 Tree
    LuoguP4178Tree难度:省选/NOI-标签:点分治\(\mathtt{blog}\)\(n\)个点的树,边\((u_i,v_i)\)有边权\(w_i\),询问距离\(\lek\)的点对数量。数据范围:\(n\le4\times......
  • POJ 2114 Boatherds / Luogu P3806 【模板】点分治1
    POJ2114Boatherds/LuoguP3806【模板】点分治1难度:\(\mathtt{?}\)/省选/NOI-标签:点分治\(\mathtt{blog}\)\(n\)个点的树,边\((u_i,v_i)\)有边权\(w_i\),\(m\)......
  • Luogu P5676 [GZOI2017] 小z玩游戏
    P5676[GZOI2017]小z玩游戏难度:提高+/省选-标签:Tarjan建图\(\mathtt{blog}\)有\(n\)组数\((w_i,e_i)\),如果当前数值为\(w_i\)即可改变为\(e_i\),如果当前数值......