BZOJ 1443 [JSOI2009]游戏Game

Posted 诚叙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1443 [JSOI2009]游戏Game相关的知识,希望对你有一定的参考价值。

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1443

分析:对于这种棋子在棋盘上走来走去,只能走相邻的格子的问题,感觉还是挺好玩的...

  然后好玩归好玩,可是有点不会做啊.

  貌似棋盘上相邻格子这种不断移动的问题,都大概能扯到一点网络流吧.

  咦,二分图?唔...在二分图上走来走去.最后不能走的人算输?...

  吖,然后结论就是:求一个最大匹配,只要放在非匹配点上就可以啦...

  为什么呢?

  如果放在非匹配点,那么对手只能走到匹配点上去[不然就是走到非匹配点,然后增广了,就和最大匹配不符合了...]

  但是对手走到了匹配点上,我就一定能沿着匹配边往后走.

  然后就是对手走一条不是匹配边的边,但是他到达的点一定有一条连出去的匹配边,不然就是找到了一条增广路,与最大匹配不符.

 

  好神奇啊!

  但是我们发现可能的最大匹配不止一种.

  而且对于每一种可能的最大匹配,所有不在最大匹配中的点都可以作为最优点.

  所以统计方案还有技巧.

  

  求解方案步骤:

  1.从s出发,找到所有能到达的,属于X集合的点.

  能到达的这个部分包括:一是非匹配点(直接到达),二是经过一个非匹配点,然后走一条类似增广路所到达的匹配点(即可以将这条路上的匹配边和非匹配边翻转得到另一组解,而这条路的终点就是另一组解中的非匹配点)

  2.从t出发,倒着找到所有能到达t的点[也就是沿着反向弧为0的边前进],属于Y集合的点

  能到达t的部分包括:一是非匹配点(直接到达),二是一个匹配点,经过匹配边再到匹配边再到某个非匹配点然后到达t的过程[原理和上面的类似].

 

  然后就比较好打了...不过似乎窝代码有点丑陋的样子= =...

技术分享
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 
  5 using namespace std;
  6 
  7 const int maxn=10010;
  8 const int INF=0x3f3f3f3f;
  9 
 10 struct Node{
 11     int data,next,low;
 12 }node[1000010];
 13 
 14 #define www node[point].low
 15 #define now node[point].data
 16 #define then node[point].next
 17 
 18 int n,m,cnt;
 19 int s,t;
 20 int que[maxn],dis[maxn];
 21 int head[maxn],cur[maxn];
 22 int tp[maxn],rx[maxn],ry[maxn];
 23 int stack[maxn],top;
 24 int id[110][110],Idex;
 25 int x[4]={0,0,1,-1},y[4]={1,-1,0,0};
 26 char ch[110][110];
 27 bool vis[maxn];
 28 
 29 struct Pot{
 30     int x,y;
 31 }a[maxn];
 32 
 33 bool cmp(const Pot &A,const Pot &B){
 34     if(A.x!=B.x) return A.x<B.x;
 35     return A.y<B.y;
 36 }
 37 
 38 inline void add(int u,int v,int w){
 39     node[cnt].data=v;node[cnt].next=head[u];node[cnt].low=w;head[u]=cnt++;
 40     node[cnt].data=u;node[cnt].next=head[v];node[cnt].low=0;head[v]=cnt++;
 41 }
 42 
 43 bool BFS(){
 44     memset(dis,-1,sizeof(dis));
 45     
 46     int H=0,T=1,k;que[1]=s;dis[s]=0;
 47     
 48     while(H<T){
 49         k=que[++H];
 50         for(int point=head[k];point!=-1;point=then)
 51             if(www && dis[now]<0)
 52                 dis[now]=dis[k]+1,que[++T]=now;
 53     }
 54     return dis[t]>0;
 55 }
 56 
 57 int dfs(int x,int low){
 58     if(x==t) return low;
 59     for(int &point=cur[x];point!=-1;point=then)
 60         if(www && dis[now]==dis[x]+1){
 61             int Low=dfs(now,min(www,low));
 62             if(Low){
 63                 www-=Low,node[point^1].low+=Low;
 64                 return Low;
 65             }
 66         }
 67     return 0;
 68 }
 69 
 70 void Build(){
 71     int nx,ny;
 72     
 73     for(int i=1;i<=n;i++)
 74     for(int j=1;j<=m;j++)
 75         if(ch[i][j]==.){
 76             id[i][j]=++Idex;
 77             rx[Idex]=i,ry[Idex]=j;
 78         }
 79     s=0;t=Idex+1;
 80     for(int i=s;i<=t;i++) head[i]=-1;
 81     
 82     for(int i=1;i<=n;i++)
 83     for(int j=1;j<=m;j++)
 84     if(ch[i][j]==.){
 85         if((i^j)&1){
 86             add(s,id[i][j],1);
 87             tp[id[i][j]]=1;
 88             for(int k=0;k<4;k++){
 89                 nx=i+x[k],ny=j+y[k];
 90                 if(nx>n || nx<1 || ny<1 || ny>m || ch[nx][ny]==#) continue;
 91                 add(id[i][j],id[nx][ny],1);
 92             }
 93         }
 94         else
 95             add(id[i][j],t,1),tp[id[i][j]]=2;
 96     }
 97 }
 98 
 99 void Calcu(int x,int d){
100     vis[x]=1;
101     if(tp[x]==d) stack[++top]=x;
102     for(int point=head[x];point!=-1;point=then)
103     if(!vis[now] && www==(d!=2)) Calcu(now,d);
104 }
105 
106 int main(){
107 #ifndef ONLINE_JUDGE
108     freopen("1443.in","r",stdin);
109     freopen("1443.out","w",stdout);
110 #endif
111     
112     int flag,rec;
113     
114     scanf("%d%d",&n,&m);
115     for(int i=1;i<=n;i++)
116         scanf("%s",ch[i]+1);
117     
118     Build();
119     rec=Idex;
120     while(BFS()){
121         memcpy(cur,head,sizeof(head));
122         while(flag=dfs(s,INF)) Idex-=(flag<<1);
123     }
124     
125     if(!Idex){
126         puts("LOSE");
127     }
128     else{
129         puts("WIN");
130         
131         Calcu(s,1);
132         memset(vis,0,sizeof(vis));
133         Calcu(t,2);
134         
135         for(int i=1;i<=top;i++){
136             a[i].x=rx[stack[i]];
137             a[i].y=ry[stack[i]];
138         }
139         sort(a+1,a+top+1,cmp);
140         for(int i=1;i<=top;i++)
141             printf("%d %d\n",a[i].x,a[i].y);
142     }
143     return 0;
144 }
View Code

 

  

以上是关于BZOJ 1443 [JSOI2009]游戏Game的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1443 [JSOI2009]游戏Game

BZOJ:1443: [JSOI2009]游戏Game

BZOJ1443: [JSOI2009]游戏Game

BZOJ1444[Jsoi2009]有趣的游戏 AC自动机+概率DP+矩阵乘法

●BZOJ 1444 [Jsoi2009]有趣的游戏

[bzoj1452][JSOI2009]Count(树状数组)