zoukankan      html  css  js  c++  java
  • 【HDU 1569 方格取数(2)】 网络流

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1569

    题目大意:给你一个m*n的格子的棋盘,每个格子里面有一个非负数。
                从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大。

    解题思路:说实话,这样的网络流构图真的难想到,唉,练得太少了。

    定理: 最大点独立集=sum-最小点覆盖集。

             这里要我们求最大点独立集,由上面的定理我们就可以转换为求最小点覆盖集。我发现网上很多题解对于割这一块讲解的不知所云,可能是对割的理解还没深入吧,不会就看别人解题报告,然后自己按照自己的理解不知所云的讲。 这题可以用类似国际象棋黑白棋的方法解,每个点和它周围四个点连一条容量为无穷的边,源点和黑点(奇数点)相连,汇点和白点(偶数点)相连,剩下的就看你怎么割了,应该是这么割的:割掉最少最小的边,使得从源点的流量一点都不能到达汇点 ,等价于求源点到汇点的最大流。

            建好图直接上模板,此刻顿时变成渣渣题了。

    View Code
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    const int mn=3333;
    const int mm=1000000;
    const int oo=0x3fffffff;
    int node, st, sd, edge;
    int flow[mm], reach[mm], next[mm];
    int head[mn], work[mn], dis[mn], que[mn];
    
    void init(int node_, int st_, int sd_)
    {
        node=node_, st=st_, sd=sd_;
        for(int i=0; i<node; i++) head[i]=-1;
        edge=0;
    }
    
    void addedge(int u, int v, int c1, int c2)
    {
        reach[edge]=v, flow[edge]=c1,  next[edge]=head[u], head[u]=edge++;
        reach[edge]=u, flow[edge]=c2,  next[edge]=head[v], head[v]=edge++;
    }
    
    bool bfs()
    {
        int u, v, l=0, h=0;
        for(int i=0; i<node; i++) dis[i]=-1;
        que[l++]=st;
        dis[st]=0;
        while(l!=h)
        {
            u=que[h++];
            if(h==mn) h=0;
            for(int i=head[u]; i>=0; i=next[i])
            {
                v=reach[i];
                if(flow[i]&&dis[v]<0)
                {
                    dis[v]=dis[u]+1;
                    que[l++]=v;
                    if(l==mn) l=0;
                    if(v==sd) return true;
                }
            }
        }
        return false;
    }
    
    int dfs(int u, int exp)
    {
        if(u==sd) return exp;
        for(int &i=work[u]; i>=0; i=next[i])
        {
            int v=reach[i], tp;
            if(flow[i]&&dis[v]==dis[u]+1&&(tp=dfs(v,min(flow[i],exp))>0))
            {
                flow[i]-=tp;
                flow[i^1]+=tp;
                return tp;
            }
        }
        return 0;
    }
    
    int Dinic()
    {
        int max_flow=0, flow;
        while(bfs())
        {
            for(int i=0; i<node; i++) work[i]=head[i];
            while(flow=dfs(st,oo)) max_flow+=flow;
        }
        return max_flow;
    }
    
    int main()
    {
        int m;
        while(cin >> m)
        {
            init(m*m+2,0,m*m+1);
            int sum=0, val;
            for(int i=1; i<=m; i++)
                for(int j=1; j<=m; j++)
                {
                   scanf("%d",&val);
                   sum+=val;
                   if((i+j)&1)
                   {
                       addedge(st,(i-1)*m+j,val,0);
                       if(i!=1) addedge((i-1)*m+j,(i-2)*m+j,oo,0);
                       if(i!=m) addedge((i-1)*m+j,i*m+j,oo,0);
                       if(j!=1) addedge((i-1)*m+j,(i-1)*m+j-1,oo,0);
                       if(j!=m) addedge((i-1)*m+j,(i-1)*m+j+1,oo,0);
                   }
                   else addedge((i-1)*m+j,sd,val,0);
                }
            printf("%d\n",sum-Dinic());
        }
        return 0;
    }


  • 相关阅读:
    赫尔维茨公式
    从解析几何的角度分析二次型
    Struts 1 Struts 2
    记一次服务器被入侵的调查取证
    契约式设计 契约式编程 Design by contract
    lsblk df
    Linux Find Out Last System Reboot Time and Date Command 登录安全 开关机 记录 帐号审计 历史记录命令条数
    Infrastructure for container projects.
    更新文档 版本控制 多版本并发控制
    Building Microservices: Using an API Gateway
  • 原文地址:https://www.cnblogs.com/kane0526/p/2981087.html
Copyright © 2011-2022 走看看