zoukankan      html  css  js  c++  java
  • 【CODEVS】1922 骑士共存问题

    算法】二分图最大匹配(最大流)

    【题解】按(i+j)奇偶性染色后,发现棋子跳到的地方刚好异色。

    然后就是二分图了,对于每个奇点向可以跳到的地方连边,偶点不需连(可逆)。

    所以题目要求转换为求二分图上最大独立集(对于每条边,至少有一个点不被选中)。

    最大独立集=总点数-最小割

    //代码略
    //hzwer's code:
    
    
    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define INF 0x7fffffff
    using namespace std;
    int n,m,bl,wt,ans,cnt=1;
    bool del[201][201];
    int mark[201][201];
    int xx[8]={1,1,2,2,-1,-1,-2,-2},
        yy[8]={2,-2,1,-1,2,-2,1,-1};
    struct data{int to,next,v;}e[500001];
    int head[40002],h[40002];
    void insert(int u,int v,int w)
    {
         cnt++;
         e[cnt].to=v;
         e[cnt].next=head[u];
         head[u]=cnt;
         e[cnt].v=w;
         cnt++;
         e[cnt].to=u;
         e[cnt].next=head[v];
         head[v]=cnt;
     }
    void build()
    {
         for(int i=1;i<=n;i++)
             for(int j=1;j<=n;j++)
                 if(del[i][j])continue;
                 else if(mark[i][j]<bl)
                 {
                 for(int k=0;k<8;k++)
                 {
                         int nowx=i+xx[k],nowy=j+yy[k];
                         if(nowx<1||nowy<1||nowx>n||nowy>n||del[nowx][nowy])continue;
                         insert(mark[i][j],mark[nowx][nowy],INF);
                         }
                 insert(0,mark[i][j],1);
                 }
                 else insert(mark[i][j],wt,1);
     }
    bool bfs()
    {
         int q[40002],t=0,w=1,i,now;
         memset(h,-1,sizeof(h));
         h[0]=q[0]=0;
         while(t<w)
         {
                   now=q[t];t++;
                   i=head[now];
                   while(i)
                   {
                           if(h[e[i].to]==-1&&e[i].v){h[e[i].to]=h[now]+1;q[w++]=e[i].to;}
                           i=e[i].next;
                           }
                   }
         if(h[wt]==-1)return 0;
         return 1;
     }
    int dfs(int x,int f)
    {
        if(x==wt)return f;
        int i=head[x];
        int w,used=0;
        while(i)
        {
                if(e[i].v&&h[e[i].to]==h[x]+1)
                {
                    w=f-used;
                    w=dfs(e[i].to,min(w,e[i].v));   
                    e[i].v-=w;
                    e[i^1].v+=w;
                    used+=w;
                    if(used==f)return f;                      
                    }
                    i=e[i].next;
                }
        if(!used)h[x]=-1;
        return used;
        }
    void dinic(){while(bfs()){ans+=dfs(0,INF);}}
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
                int x,y;
                scanf("%d%d",&x,&y);
                del[x][y]=1;
                }
        bl=1,wt=(n*n+1)/2+1;
        for(int i=1;i<=n;i++)
           for(int j=1;j<=n;j++)
              if((i+j)%2==0){mark[i][j]=bl;bl++;}
              else {mark[i][j]=wt;wt++;}
        build();
        dinic();
        printf("%d",n*n-m-ans);
        return 0;
    }
    View Code
  • 相关阅读:
    Django中的syncdb命令
    notepad++下的字体设置
    python中的getattr函数
    python实现虚拟茶话会
    利用python爬取海量疾病名称百度搜索词条目数的爬虫实现
    SQL里面如何取得前N条数据?
    python中怎么查看当前工作目录和更改工作目录
    python中thread模块中join函数
    python中的自测语句是什么?
    python读取数据库数据有乱码怎么解决?
  • 原文地址:https://www.cnblogs.com/onioncyc/p/6498555.html
Copyright © 2011-2022 走看看