首页 > 代码库 > HDU1569 最大流(最大点权独立集)

HDU1569 最大流(最大点权独立集)

方格取数(2)

Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 68 Accepted Submission(s): 33
 
Problem Description
给你一个m*n的格子的棋盘,每个格子里面有一个非负数。
从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大。
 
Input
包括多个测试实例,每个测试实例包括2整数m,n和m*n个非负数(m<=50,n<=50)
 
Output

            对于每个测试实例,输出可能取得的最大的和
 
Sample Input
3 3
75 15 21 
75 15 28 
34 70 5
 
Sample Output
188
 
Author
ailyanlu
 
Source
Happy 2007
 

代码:

//类似于二分图中求最大独立集,但这里带权值。看成二分图,把点数换成奇偶数,(x+y为奇/偶),
//因为奇数和偶数相邻不能同时取,我们把相互冲突的做边(权值为无穷大),左边加一个源点
//连接所有奇数,右边加一个汇点连接所有偶数(权值为点权值,建边时边的方向要一致),就有了
//最大流模型,最大流求出来的就是最小点权覆盖。二分图中 最大独立集=总点数-最小点覆盖(最
//大匹配);类似 最大点权独立集=总点权值-最小点权覆盖
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=2505,inf=0x7fffffff;
struct edge{
    int from,to,cap,flow;
    edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};
struct dinic{
    int n,m,s,t;
    vector<edge>edges;
    vector<int>g[maxn];
    bool vis[maxn];
    int d[maxn];
    int cur[maxn];
    void init(int n){
        this->n=n;
        for(int i=0;i<n;i++) g[i].clear();
        edges.clear();
    }
    void addedge(int from,int to,int cap){
        edges.push_back(edge(from,to,cap,0));
        edges.push_back(edge(to,from,0,0));//反向弧
        m=edges.size();
        g[from].push_back(m-2);
        g[to].push_back(m-1);
    }
    bool bfs(){
        memset(vis,0,sizeof(vis));
        queue<int>q;
        q.push(s);
        d[s]=0;
        vis[s]=1;
        while(!q.empty()){
            int x=q.front();q.pop();
            for(int i=0;i<(int)g[x].size();i++){
                edge&e=edges[g[x][i]];
                if(!vis[e.to]&&e.cap>e.flow){
                    vis[e.to]=1;
                    d[e.to]=d[x]+1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    int dfs(int x,int a){
        if(x==t||a==0) return a;
        int flow=0,f;
        for(int&i=cur[x];i<(int)g[x].size();i++){
            edge&e=edges[g[x][i]];
            if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){
                e.flow+=f;
                edges[g[x][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if(a==0) break;
            }
        }
        return flow;
    }
    int maxflow(int s,int t){
        this->s=s;this->t=t;
        int flow=0;
        while(bfs()){
            memset(cur,0,sizeof(cur));
            flow+=dfs(s,inf);
        }
        return flow;
    }
}dc;
int main()
{
    int m,n;
    while(scanf("%d%d",&m,&n)==2){
        int sum=0,tmp[55][55];
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++){
                scanf("%d",&tmp[i][j]);
                sum+=tmp[i][j];
            }
        dc.init(n*m+2);
        int s=0,t=n*m+1;
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++){
                int nu=(i-1)*n+j;
                if((i+j)%2){
                    dc.addedge(s,nu,tmp[i][j]);
                    if(i>1) dc.addedge(nu,nu-n,inf);
                    if(i<m) dc.addedge(nu,nu+n,inf);
                    if(j>1) dc.addedge(nu,nu-1,inf);
                    if(j<n) dc.addedge(nu,nu+1,inf);
                }
                else dc.addedge(nu,t,tmp[i][j]);
            }
        int x=dc.maxflow(s,t);
        printf("%d\n",sum-x);
    }
    return 0;
}

 

HDU1569 最大流(最大点权独立集)