734. [网络流24题] 方格取数问题 二分图点权最大独立集/最小割/最大流

?问题描述:
在一个有m*n 个方格的棋盘中,每个方格中有一个正整数。现要从方格中取数,使任
意2 个数所在方格没有公共边,且取出的数的总和最大。试设计一个满足要求的取数算法。
?编程任务:
对于给定的方格棋盘,按照取数要求编程找出总和最大的数。
?数据输入:
由文件grid.in提供输入数据。文件第1 行有2 个正整数m和n,分别表示棋盘的行数
和列数。接下来的m行,每行有n个正整数,表示棋盘方格中的数。

【问题分析】

二分图点权最大独立集,转化为最小割模型,从而用最大流解决。

【建模方法】

首先把棋盘黑白染色,使相邻格子颜色不同,所有黑色格子看做二分图X集合中顶点,白色格子看做Y集合顶点,建立附加源S汇T。

1、从S向X集合中每个顶点连接一条容量为格子中数值的有向边。
2、从Y集合中每个顶点向T连接一条容量为格子中数值的有向边。
3、相邻黑白格子Xi,Yj之间从Xi向Yj连接一条容量为无穷大的有向边。

求出网络最大流,要求的结果就是所有格子中数值之和减去最大流量。

【建模分析】

这是一个二分图最大点权独立集问题,就是找出图中一些点,使得这些点之间没有边相连,这些点的权值之和最大。独立集与覆盖集是互补的,求最大点权独立集可以转化为求最小点权覆盖集(最小点权支配集)。最小点权覆盖集问题可以转化为最小割问题解决。结论:最大点权独立集 = 所有点权 - 最小点权覆盖集 = 所有点权 - 最小割集 = 所有点权 - 网络最大流。

对于一个网络,除去冗余点(不存在一条ST路径经过的点),每个顶点都在一个从S到T的路径上。割的性质就是不存在从S到T的路径,简单割可以认为割边关联的非ST节点为割点,而在二分图网络流模型中每个点必关联到一个割点(否则一定还有增广路,当前割不成立),所以一个割集对应了一个覆盖集(支配集)。最小点权覆盖集就是最小简单割,求最小简单割的建模方法就是把XY集合之间的变容量设为无穷大,此时的最小割就是最小简单割了。

/*
 * Problem: 线性规划与网络流24题 #9 方格取数问题
 * Author: Guo Jiabao
 * Time: 2009.6.27 19:06
 * State: Solved
 * Memo: 网络最大流 二分图点权最大独立集
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
using namespace std;
const int MAXL=50,MAXN=50*50,MAXM=MAXN*8,INF=~0U>>1;
const int dx[]={0,0,-1,1},dy[]={-1,1,0,0};
struct edge
{
    edge *next,*op;
    int t,c;
}*V[MAXN],*P[MAXN],ES[MAXM],*Stae[MAXN];
int N,M,S,T,C,EC,Ans,Maxflow,Total;
int Lv[MAXN],Stap[MAXN],Map[MAXL][MAXL];
inline void addedge(int a,int b,int c)
{
    ES[++EC].next = V[a]; V[a]=ES+EC; V[a]->t=b; V[a]->c=c;
    ES[++EC].next = V[b]; V[b]=ES+EC; V[b]->t=a; V[b]->c=0;
    V[a]->op = V[b]; V[b]->op = V[a];
}
void init()
{
    int i,j,k,c;
    freopen("grid.in","r",stdin);
    freopen("grid.out","w",stdout);
    scanf("%d%d",&M,&N);
    S=0; T=N*M+1;
    for (i=1;i<=M;i++)
    {
        for (j=1;j<=N;j++)
        {
            scanf("%d",&c);
            Total += c;
            Map[i][j] = ++C;
            if ((i+j)%2==0)
                addedge(S,C,c);
            else
                addedge(C,T,c);
        }
    }
    for (i=1;i<=M;i++)
    {
        for (j=1;j<=N;j++)
        {
            if ((i+j)%2==0)
            {
                for (k=0;k<4;k++)
                {
                    int x=i+dx[k],y=j+dy[k];
                    if (x>=1 && x<=M && y>=1 && y<=N)
                        addedge(Map[i][j],Map[x][y],INF);
                }
            }
        }
    }
}
bool Dinic_Label()
{
    int head,tail,i,j;
    Stap[head=tail=0]=S;
    memset(Lv,-1,sizeof(Lv));
    Lv[S]=0;
    while (head<=tail)
    {
        i=Stap[head++];
        for (edge *e=V[i];e;e=e->next)
        {
            j=e->t;
            if (e->c && Lv[j]==-1)
            {
                Lv[j] = Lv[i]+1;
                if (j==T)
                    return true;
                Stap[++tail] = j;
            }
        }
    }
    return false;
}
void Dinic_Augment()
{
    int i,j,delta,Stop;
    for (i=S;i<=T;i++)
        P[i] = V[i];
    Stap[Stop=1]=S;
    while (Stop)
    {
        i=Stap[Stop];
        if (i!=T)
        {
            for (;P[i];P[i]=P[i]->next)
                if (P[i]->c && Lv[i] + 1 == Lv[j=P[i]->t])
                    break;
            if (P[i])
            {
                Stap[++Stop] = j;
                Stae[Stop] = P[i];
            }
            else
                Stop--,Lv[i]=-1;
        }
        else
        {
            delta = INF;
            for (i=Stop;i>=2;i--)
                if (Stae[i]->c < delta)
                    delta = Stae[i]->c;
            Maxflow += delta;
            for (i=Stop;i>=2;i--)
            {
                Stae[i]->c -= delta;
                Stae[i]->op->c += delta;
                if (Stae[i]->c==0)
                    Stop = i-1;
            }
        }
    }
}
void Dinic()
{
    while (Dinic_Label())
        Dinic_Augment();
}
int main()
{
    init();
    Dinic();
    Ans = Total - Maxflow;
    printf("%d\n",Ans);
    return 0;
}
时间: 2024-10-25 16:31:00

734. [网络流24题] 方格取数问题 二分图点权最大独立集/最小割/最大流的相关文章

网络流24题-方格取数

题目 方格中取数若干,两两不相邻,求最大选数和. 样例: 3 3 1 2 3 3 2 3 2 3 1 输出: 11 ans=2+3+3+3=11 黑白染色 建成二分图: 中间这些边连成INF(即不限制流量) 其实就是求最大独立集 定理:|二分图最大独立集|=|顶点数|-|二分图最大匹配数| 这个,我不会证明. 所以:|二分图最大独立集|=|总价值|-|二分图最大匹配价值| 考虑构图:s=>黑点=>白点=>t 首先,对与第[i][j]格,有价值为val[i][j] edge(s,黑点,va

网络流 24题 方格取数

方格取数问题 题目描述 在一个有m*n个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意2个数所在方格没有公共边,且取出的数的总和最大.试设计一个满足要求的取数算法. 输入格式 文件第1行有2个正整数m和n,分别表示棋盘的行数和列数.接下来的m行,每行有n个正整数,表示棋盘方格中的数.(0 <= m, n <= 30) 输出格式 取数的最大总和. 输入样例 33 1 2 3 3 2 3 2 3 1 输出样例 11 题目大意:     给出m*n的格子,相邻的格子的值不可同时取,最

[网络流24题] 方格取数问题

题面: 传送门 思路: 相邻的点不能同时取,那么在这个图中,实际上分了两种格子,每种格子相互之间随便取 那么就是二分图了 把相邻的点之间连边,得到一个二分图,我们实际上就是要求这个图的带权最大独立集 于是这道题转化为二分图问题,而二分图中最大独立集等于全集减去最小点覆盖,最小点覆盖等于这个图的最大匹配(都带权) 那么用网络流做就好了 将这个平面上的方格像国际象棋那样黑白染色 源点连黑点,容量为黑点权值 黑点连白点,容量为inf 白点连汇点,容量为白点权值 跑S-T最大流(即S-T最小割),用所有

[luogu2774] [网络流24题] 方格取数问题

传送门 某个方格如果选了,那么其周边的四个方格都不能选,有点二分图染色的味道. 考虑建立一个二分图.源点向\(x+y\)是奇数的连边,是偶数的向汇点连边. 然后根据最大和 = 全局和 - 舍弃和 = 全局和 - 最大流,求解 可以理解为在这个二分图中存在一个简单割,有一些点就被舍弃掉了,剩下的点就是我们要需选取的. #include <queue> #include <cstdio> #include <cstring> #include <algorithm&g

hdu1569 方格取数(2) 二分图最大点权独立集

题意:中文题.. 思路:首先根据横纵坐标之和的奇偶转化成二分图,对于( i , j )来说与它冲突的只有(i - 1 , j ) ( i , j - 1 ) ( i + 1 , j ) ( i  , j + 1 )4个方格, 奇偶性相反.如果i + j是奇数那么和周围4点连边,那么问题转化求所有点权和 - 该二分图的最小点权覆盖 .我们关注最小点权覆盖 模型,建立超级起点st,超级终点ed, 对于二分图左边的点( i+j为奇数) ,从st向点连一条边,边权为该点的权值,对于二分图右边的 点,从点

XTU 二分图和网络流 练习题 C. 方格取数(1)

C. 方格取数(1) Time Limit: 5000ms Memory Limit: 32768KB 64-bit integer IO format: %I64d      Java class name: Main 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大. Input 包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数(n<=20) Output 对

网络流 [HDU 1565] 方格取数(1)

方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5961    Accepted Submission(s): 2268 Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数

网络流24题-飞行员配对方案问题-二分图最大匹配

这道题,是个人都看得出来,是求一个二分图的最大匹配. 但是网络流24题嘛,我们考虑一下用网络流的方法做. 一般二分图的题,转网络流做,都需要建立一个起点和汇点.然后求一个最大流,这个最大流就是二分图的最大匹配. 我用的是Edmonds-Karp算法bfs版本 代码 #include<iostream> #include<string.h> #include<stdio.h> #include<algorithm> #include<queue>

[luoguP2774] 方格取数问题(最大点权独立集)

传送门 引入两个概念: 最小点权覆盖集:满足每一条边的两个端点至少选一个的最小权点集. 最大点权独立集:满足每一条边的两个端点最多选一个的最大权点集. 现在对网格染色,使得相邻两点颜色不同,之后把两个颜色的点分成两个集合X,Y.S向X集合每个点连一条该点权值的边,Y集合每个点向T连一条该点权值的边,原来的边流量全部变为INF.这个网络的最小割为最小点权覆盖集.因为这个最小割满足了,对于中间每一条边,两端的点必定选择了一个.若一个都没有选择则S与T仍连通.且因为中间的边流量为INF所以不会是中间被