hrbust 2163 棋盘取数【最大权独立集合-------最大流Dinic】

来源:互联网 发布:sql server授权语句 编辑:程序博客网 时间:2024/05/20 04:51

棋盘取数Time Limit: 1000 MSMemory Limit: 32768 KTotal Submit: 58(18 users)Total Accepted: 13(8 users)Rating: Special Judge: NoDescription

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

Input

包括多个测试实例,每个测试实例包括一个整数n 和n*n个非负数x(n<=20, 0 <= x <= 1000)。

Output

对于每个测试实例,输出可能取得的最大的和。

Sample Input

3

258 83 905

874 941 662

733 415 890

Sample Output

3727

Source2014暑假集训练习赛(8月13日)


思路


1、首先,这个题是一个二分图模型。并且我们知道最大权独立集=总权-最小割=总权-最大流。


2、那么我们就在以上基础建图。

①我们将点分成两个集合,i+j为偶数的点我们规定为一个集合,那么i+j为奇数的点就是另一个集合。

②源点S和i+j为偶数的点都进行建边,其容量为a【i】【j】,i+j为奇数的点和汇点t都进行建边,其容量也是a【i】【j】;

③将i+j为偶数的点和周围四个点进行建边,其容量为无穷大。


3、求一遍最大流,其解为:总权-最大流、


4、Ford_Fulkerson 、Edmond _Karp都是不可行算法(数据将两种算法都卡了TLE)。



Ac:


#include<stdio.h>#include<string.h>#include<queue>using namespace std;#define INF 0x3f3f3f3fint head[100000];struct EdgeNode{    int to;    int w;    int next;}e[1000000];int div[100000];int a[25][25];int fx[4]={0,0,1,-1};int fy[4]={1,-1,0,0};int n,cont,ss,tt;void add(int from,int to,int w){    e[cont].to=to;    e[cont].w=w;    e[cont].next=head[from];    head[from]=cont++;}void getmap(){    ss=n*n+1;    tt=ss+1;    cont=0;    memset(head,-1,sizeof(head));    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)        {            if((i+j)%2==0)            {                add(ss,(i-1)*n+j,a[i][j]);                add((i-1)*n+j,ss,0);            }            else            {                add((i-1)*n+j,tt,a[i][j]);                add(tt,(i-1)*n+j,0);            }        }    }    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)        {            if((i+j)%2==1)continue;            for(int k=0;k<4;k++)            {                int x=i+fx[k];                int y=j+fy[k];                if(x>=1&&x<=n&&y>=1&&y<=n)                {                    add((i-1)*n+j,(x-1)*n+y,INF);                    add((x-1)*n+y,(i-1)*n+j,0);                }            }        }    }}int makediv(){    memset(div,0,sizeof(div));    div[ss]=1;    queue<int >s;    s.push(ss);    while(!s.empty())    {        int u=s.front();        if(u==tt)return 1;        s.pop();        for(int i=head[u];i!=-1;i=e[i].next)        {            int v=e[i].to;            int w=e[i].w;            if(w&&div[v]==0)            {                div[v]=div[u]+1;                s.push(v);            }        }    }    return 0;}int Dfs(int u,int maxflow,int tt){    if(u==tt)return maxflow;    int ret=0;    for(int i=head[u];i!=-1;i=e[i].next)    {        int v=e[i].to;        int w=e[i].w;        if(w&&div[v]==div[u]+1)        {            int f=Dfs(v,min(maxflow-ret,w),tt);            e[i].w-=f;            e[i^1].w+=f;            ret+=f;            if(ret==maxflow)return ret;        }    }    return ret;}int Dinic(){    int ans=0;    while(makediv()==1)    {        ans+=Dfs(ss,INF,tt);    }    return ans;}int main(){    while(~scanf("%d",&n))    {        int output=0;        for(int i=1;i<=n;i++)        {            for(int j=1;j<=n;j++)            {                scanf("%d",&a[i][j]);                output+=a[i][j];            }        }        getmap();        output-=Dinic();        printf("%d\n",output);    }}



0 0