zoukankan      html  css  js  c++  java
  • 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
    ",a[i].x,a[i].y);
    142     }
    143     return 0;
    144 }
    View Code

      

  • 相关阅读:
    Coding Souls团队---电梯演讲
    第一次团队会议总结-NABCD分析
    软件工程团队项目介绍
    python进行四舍五入
    python列表元素两两比较
    Linux常用命令
    谷歌日历的正确用法--在谷歌日历中添加农历、天气、中国节假日
    Nose框架的安装
    python中staticmethod装饰器的作用
    python 3.x与python 2.7.x在语法上的区别
  • 原文地址:https://www.cnblogs.com/Robert-Yuan/p/5350631.html
Copyright © 2011-2022 走看看