zoukankan      html  css  js  c++  java
  • BZOJ 4808: 马(二分图最大点独立集)

     http://www.lydsy.com/JudgeOnline/problem.php?id=4808

    题意:

     

    思路:

    这图中的两个马只能选一个,二选一,很像二分图吧,对能互吃的两个棋子连线,在所选的任意两个棋子中,都不能互相有连线,这不就是最大点独立集吗?

    最大独立集 = 顶点个数 - 最大匹配。记得把坏了的格子去掉。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    int n,m,tot;
    int mp[205][205], head[40005], mark[40005];
    bool vis[40005];
    
    struct node
    {
        int v,next;
    }e[8*40005];
    
    int dx[] = {-2,-2,-1,-1,1,1,2,2};
    int dy[] = {1,-1,2,-2,2,-2,1,-1};
    
    void addEdge(int u, int v)
    {
        e[tot].v = v;
        e[tot].next = head[u];
        head[u] = tot++;
    }
    
    bool match(int u)
    {
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v = e[i].v;
            if(!vis[v])
            {
                vis[v] = true;
                if(mark[v]==-1 || match(mark[v]))
                {
                    mark[v] = u;
                    return true;
                }
            }
        }
        return false;
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int num = 0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&mp[i][j]);
            if(mp[i][j]) num++;
        }
        tot = 0;
        memset(head,-1,sizeof(head));
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(!mp[i][j])
            {
                for(int k=0;k<8;k++)
                {
                    int x = i+dx[k];
                    int y = j+dy[k];
                    if(x<1 || x>n || y<1 || y>m)  continue;
                    if(mp[x][y]==1)  continue;
                    int p1 = (i-1)*m+j;
                    int p2 = (x-1)*m+y;
                    addEdge(p1,p2);
                }
            }
        }
        int sum = 0;
        memset(mark,-1,sizeof(mark));
        for(int i=1;i<=n*m;i++)
        {
            memset(vis,false,sizeof(vis));
            if(match(i))  sum++;
        }
        printf("%d
    ",n*m-num-sum/2);
        return 0;
    }
    

      

  • 相关阅读:
    如何防止多个人同时编辑文件
    通过Word实现表单套打
    偏前端
    偏前端
    偏前端
    偏前端 -webpack打包之(安装webpack)
    偏前端
    偏前端
    偏前端
    偏前端--之小白学习本地存储与cookie
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7904002.html
Copyright © 2011-2022 走看看