zoukankan      html  css  js  c++  java
  • BZOJ1324Exca王者之剑&BZOJ1475方格取数——二分图最大独立集

    题目描述

     

    输入

    第一行给出数字N,M代表行列数.N,M均小于等于100 下面N行M列用于描述数字矩阵

    输出

    输出最多可以拿到多少块宝石

    样例输入

    2 2
    1 2
    2 1

    样例输出

    4
     
    题意就是选取一些点使他们互不相邻且使选取点的点权和最大。我们将网格图黑白染色,将相邻点连边,显然这是个二分图,我们要求的就是二分图的最大独立集。建模时将源点连向黑点,流量为点权;黑点连向与它相邻的白点,流量为$INF$;将白点连向汇点,流量为点权。答案就是总点权和$-$最小割,被割的边所连点就是不选取的点。因为最小割使源汇点不连通,所以所有选取的黑点都不会流向白点,所有选取的白点不会有黑点流过来,即相邻的点不会被同时选取。
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    using namespace std;
    int head[12000];
    int next[50000];
    int to[50000];
    int val[50000];
    int d[12000];
    int q[12000];
    int n,m;
    int tot=1;
    int ans=0;
    int S,T;
    int s[200][200];
    void add(int x,int y,int v)
    {
        tot++;
        next[tot]=head[x];
        head[x]=tot;
        to[tot]=y;
        val[tot]=v;
        tot++;
        next[tot]=head[y];
        head[y]=tot;
        to[tot]=x;
        val[tot]=0;
    }
    bool bfs(int S,int T)
    {
        int r=0;
        int l=0;
        memset(q,0,sizeof(q));
        memset(d,-1,sizeof(d));
        q[r++]=S;
        d[S]=0;
        while(l<r)
        {  
            int now=q[l];
            for(int i=head[now];i;i=next[i])
            {
                if(d[to[i]]==-1&&val[i]!=0)
                {
                    d[to[i]]=d[now]+1;
                    q[r++]=to[i];
                }
            }
            l++;
        }
        return d[T]!=-1;
    }
    int dfs(int x,int flow)
    {
        if(x==T)
        {
            return flow;
        }
        int now_flow;
        int used=0;
        for(int i=head[x];i;i=next[i])
        {
            if(d[to[i]]==d[x]+1&&val[i]!=0)
            {
                now_flow=dfs(to[i],min(flow-used,val[i]));
                val[i]-=now_flow;
                val[i^1]+=now_flow;
                used+=now_flow;
                if(now_flow==flow)
                {
                    return flow;
                }
            }
        }
        if(used==0)
        {
            d[x]=-1;
        }
        return used;
    }
    void dinic()
    {
        while(bfs(S,T)==true)
        {
            ans-=dfs(S,0x3f3f3f);
        }
    }
    int main()
    {
        scanf("%d%d",&m,&n);
        S=n*m+1;
        T=n*m+2;
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&s[i][j]);
                ans+=s[i][j];
                if((i+j)%2==0)
                {
                    add(S,n*(i-1)+j,s[i][j]);
                }
                else
                {
                    add(n*(i-1)+j,T,s[i][j]);
                }
            }
        }
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if((i+j)%2==0)
                {
                    if(i-1>0)
                    {
                        add(n*(i-1)+j,n*(i-2)+j,1<<30);
                    }
                    if(j-1>0)
                    {
                        add(n*(i-1)+j,n*(i-1)+j-1,1<<30);
                    }
                    if(i+1<=m)
                    {
                        add(n*(i-1)+j,n*i+j,1<<30);
                    }
                    if(j+1<=n)
                    {
                        add(n*(i-1)+j,n*(i-1)+j+1,1<<30);
                    }
                }
            }
        }
        dinic();
        printf("%d",ans);
    }
  • 相关阅读:
    安卓开发_浅谈TimePicker(时间选择器)
    eclipse显示代码行数
    Java数据解析---JSON
    Java数据解析---PULL
    Java数据解析---SAX
    统计机器学习(目录)
    FP Tree算法原理总结
    梯度下降(Gradient Descent)小结
    用scikit-learn和pandas学习线性回归
    用scikit-learn学习BIRCH聚类
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/10570906.html
Copyright © 2011-2022 走看看