<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      博客園 首頁 私信博主 顯示目錄 隱藏目錄 管理 動畫

      CCPC2020 長春. H. Combination Lock(二分圖博弈 最大流ISAP)

      題目鏈接
      ??沒好好復(fù)習(xí)以前學(xué)的,出了道模板真就看都看不出來。


      總結(jié)一下二分圖匹配(原來真就只能出板子?),其它變型可以見JSOI2019 游戲NOI2011 兔兔與蛋蛋游戲,還有一個板子
      條件:
      操作可以視為在一個二分圖上進(jìn)行,每次從一部分走到另一部分,且不會走走過的點(diǎn)。
      做法:
      若某點(diǎn)(某狀態(tài))一定在最大匹配上,則處于該點(diǎn)時先手必勝;否則存在某種匹配使得該點(diǎn)不在最大匹配上,則處于該點(diǎn)時先手必?cái) #ㄗC明見JSOI2019 游戲
      判斷某點(diǎn)是否一定在最大匹配上:
      做法1: 保留該點(diǎn)求最大匹配,刪掉該點(diǎn)再求最大匹配,看匹配數(shù)是否減少(做的時候反過來,先讓該點(diǎn)不與\(S/T\)相連求匹配數(shù),再加上該點(diǎn)到\(S/T\)的邊求(其它邊加上就行啊))。可以用網(wǎng)絡(luò)流復(fù)雜度\(O(能過)\)
      做法2: 先求最大匹配,若該點(diǎn)未被匹配則肯定是。然后枚舉所有未被匹配點(diǎn)\(x\),記與\(x\)有邊的點(diǎn)為\(to\),所有已與\(to\)匹配的點(diǎn)\(lk[to]\)可以不在最大匹配上。可以直接匈牙利,復(fù)雜度\(O(nm)\);或者網(wǎng)絡(luò)流后再DFS,復(fù)雜度\(O(能過+n+m)\)

      因?yàn)榉椒?要兩遍網(wǎng)絡(luò)流,比方法2的一遍慢的多(甚至慢一倍多?)。


      \(Description\)
      有一個有\(m\)位數(shù)字的鎖(每位為\(0\)\(9\)),初始狀態(tài)給定。\(Alice,Bob\)輪流操作,每次操作可以更改一位數(shù)字(加一或減一),且改后狀態(tài)不能和之前出現(xiàn)過的重復(fù),且不能出現(xiàn)在給定的\(n\)種狀態(tài)中。\(Alice\)先手,不能操作的人輸,問誰能贏。
      \(m\leq5,n\lt 10^m,10組數(shù)據(jù)\)

      \(Solution\)
      每次操作后所有數(shù)位和的奇偶性都會改變,所以操作可以看做一個二分圖。
      然后判斷起點(diǎn)是否一定在最大匹配上就ok了。

      本地跑樣例老RE,原來是把擴(kuò)棧關(guān)了。。


      //826ms	36000KB (做法1:2028ms	34200KB)
      #include <bits/stdc++.h>
      #define pc putchar
      #define gc() getchar()
      #define pb emplace_back
      typedef long long LL;
      const int N=1e5+5,M=N*20,LIM=1e5;
      const int pw10[]={1,10,100,1000,10000,100000,1000000};
      
      int Enum,S,T,H[N],nxt[M],fr[M],to[M],cap[M],pre[N],lev[N],lk[N];
      bool odd[N],vis[N];
      
      inline int read()
      {
      	int now=0,f=1; char c=gc();
      	for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
      	for(;isdigit(c);now=now*10+c-48,c=gc());
      	return now*f;
      }
      inline void AE(int u,int v,int w)
      {
      	to[++Enum]=v, fr[Enum]=u, nxt[Enum]=H[u], H[u]=Enum, cap[Enum]=w;
      	to[++Enum]=u, fr[Enum]=v, nxt[Enum]=H[v], H[v]=Enum, cap[Enum]=0;
      }
      bool BFS()
      {
      	static int q[N];
      	int T=::T;
      	for(int i=S; i<T; ++i) lev[i]=T+1;
      	int h=0,t=1; q[0]=T, lev[T]=0;
      	while(h<t)
      	{
      		int x=q[h++];
      		for(int i=H[x]; i; i=nxt[i])
      			if(lev[to[i]]==T+1 && cap[i^1])
      				lev[to[i]]=lev[x]+1, q[t++]=to[i];
      	}
      	return lev[S]<=T;
      }
      inline int Augment()
      {
      	for(int i=T; i; i=fr[pre[i]])
      		--cap[pre[i]], ++cap[pre[i]^1];
      	return 1;
      }
      int ISAP()
      {
      	static int cur[N],num[N];
      
      	if(!BFS()) return 0;
      	int S=::S,T=::T,res=0,x=S;
      	memset(num,0,T+1<<2);
      	for(int i=S; i<=T; ++i) cur[i]=H[i], ++num[lev[i]];
      	while(lev[S]<=T)
      	{
      		if(x==T) res+=Augment(),x=S;
      		bool can=0;
      		for(int i=cur[x]; i; i=nxt[i])
      			if(lev[to[i]]==lev[x]-1 && cap[i])
      			{
      				can=1, cur[x]=i, pre[x=to[i]]=i;
      				break;
      			}
      		if(!can)
      		{
      			int mn=T;
      			for(int i=H[x]; i; i=nxt[i])
      				if(cap[i]) mn=std::min(mn,lev[to[i]]);
      			if(!--num[lev[x]]) break;
      			++num[lev[x]=mn+1], cur[x]=H[x];
      			if(x!=S) x=fr[pre[x]];
      		}
      	}
      	return res;
      }
      void DFS(int x)
      {
      	vis[x]=1;
      	for(int i=H[x]; i; i=nxt[i])
      		if(/*lk[to[i]] && */!vis[lk[to[i]]]) DFS(lk[to[i]]);
      }
      void Solve()
      {
      	static int Ts=0; ++Ts;
      	static int ban[N];
      
      	int m=read(),n=read(),start=read();
      	Enum=1, S=0, T=pw10[m]+1;
      	while(n--) ban[read()]=Ts;
      
      	for(int i=0; i+1<T; ++i)
      		if(ban[i]!=Ts)
      		{
      			if(odd[i]) AE(i+1,T,1);
      			else AE(S,i+1,1);
      		}
      	int tmp=Enum;
      	for(int i=0; i+1<T; ++i)
      		if(ban[i]!=Ts && !odd[i])
      			for(int j=0; j<m; ++j)
      			{
      				int bit=i/pw10[j]%10,x;
      				if(bit!=9) x=i+pw10[j];
      				else x=i-9*pw10[j];
      				if(ban[x]!=Ts) AE(i+1,x+1,1);
      
      				if(bit) x=i-pw10[j];
      				else x=i+9*pw10[j];
      				if(ban[x]!=Ts) AE(i+1,x+1,1);
      			}
      	ISAP();
      //--做法1:
      //	if(odd[start]) AE(start+1,T,1);
      //	else AE(S,start+1,1);
      //	if(ISAP()) puts("Alice");
      //	else puts("Bob");
      
      //--做法2:
      	for(int i=tmp+1; i<=Enum; i+=2)
      		if(!cap[i]) assert(!lk[fr[i]]&&!lk[to[i]]),lk[fr[i]]=to[i], lk[to[i]]=fr[i];
      	vis[0]=1;//! DFS別走0。
      	for(int i=1; i<T; ++i) if(!lk[i] && !vis[i]) DFS(i);
      	puts(vis[start+1]?"Bob":"Alice");//vis=0:一定在最大匹配中 
      
      	memset(H,0,T+1<<2), memset(lk,0,T+1<<2), memset(vis,0,T+1);
      }
      
      int main()
      {
      	for(int i=0; i<LIM; ++i)
      	{
      		int x=i,t=0;
      		while(x) t+=x%10,x/=10;
      		odd[i]=t&1;
      	}
      	for(int T=read(); T--; Solve());
      
      	return 0;
      }
      
      posted @ 2021-02-24 15:48  SovietPower  閱讀(434)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 香港日本三级亚洲三级| 国精品午夜福利不卡视频| 小嫩批日出水无码视频免费| 精品国产一区二区三区av性色| 日韩成人无码影院| 亚洲男人的天堂在线观看| 国产精品自在自线免费观看| 无码国模国产在线观看免费| 97人妻熟女成人免费视频色戒| 成在线人免费视频| 日本亚洲一区二区精品| 国产中文字幕日韩精品| 国产精品美女一区二区三| 亚洲狠狠婷婷综合久久久久图片| 国产无遮挡免费视频免费| 亚洲精品一区二区动漫| 噜噜综合亚洲av中文无码| 高清中文字幕一区二区| 五原县| 国产av仑乱内谢| 亚洲欧美国产精品专区久久| 成人免费无码不卡毛片| 欧美自拍另类欧美综合图片区| 久久国产乱子精品免费女| 无码日韩精品一区二区三区免费| 亚洲精品中文av在线| 成人国产亚洲精品一区二区 | 成人午夜av在线播放| 起碰免费公开97在线视频| 国产精品久久自在自线不卡| 中文字字幕在线中文乱码| 91精品人妻中文字幕色| 亚欧美日韩香蕉在线播放视频| 377P欧洲日本亚洲大胆| 蜜臀人妻精品一区二区免费| 亚洲一区av无码少妇电影| 久热这里只精品视频99| 狠狠色丁香婷婷综合尤物| 色综合天天综合天天综| 特级精品毛片免费观看| 亚洲精品久久久久久无码色欲四季|