Hrbust oj 2163 棋盘取数(二分图+最大流)

来源:互联网 发布:知乎奇怪的问题 编辑:程序博客网 时间:2024/05/08 16:41

棋盘取数

Time Limit: 1000 MS Memory Limit: 32768 K

Total Submit: 66(22 users) Total Accepted: 18(11 users) Rating: Special Judge: No

Description

给你一个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
题解:这是个二分图,求的是最大点权独立集。最大点权独立集=总权值-最小点权覆盖。设下标和为偶数的点为X,下表和为奇数的点为Y。则ss连x,流量为mp[x],y连tt,流量为mp[y].x连周围4个点,流量为INF。
代码:

#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<vector>#include<queue>#include<stack>#include<set>#include<algorithm>#include<map>#include<time.h>#include<math.h>//#define pb push_back//#define mp make_pair#define INF 0x3f3f3f3fusing namespace std;typedef long long int ll;typedef pair<int,int>pp;const int N=1e3+100;const int mod=1e9+7;int read(){    int x=0;    char ch = getchar();    while('0'>ch||ch>'9')ch=getchar();    while('0'<=ch&&ch<='9')    {        x=(x<<3)+(x<<1)+ch-'0';        ch=getchar();    }    return x;}/***********************************************************/int fx[4]= {0,0,1,-1};int fy[4]= {1,-1,0,0};int t,n,m,u,v,c,ss,tt;int cnt,sum;struct node{    int to,w,next;} edge[N<<2];int dep[N];int vis[N];int head[N<<2];int mp[50][50];void add(int f,int to,int w){    edge[cnt].to=to;    edge[cnt].w=w;    edge[cnt].next=head[f];    head[f]=cnt++;}int makedep(){    memset(dep,0,sizeof(dep));    queue<int>s;    s.push(ss);    dep[ss]=1;    while(!s.empty())    {        int u=s.front();        if(u==tt) return 1;        s.pop();        for(int i=head[u]; i!=-1; i=edge[i].next)        {            int v=edge[i].to;            int w=edge[i].w;            if(w&&dep[v]==0)            {                dep[v]=dep[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=edge[i].next)    {        int v=edge[i].to;        int w=edge[i].w;        if(w&&dep[v]==dep[u]+1)        {            int f=dfs(v,min(maxflow-ret,w),tt);            edge[i].w-=f;            edge[i^1].w+=f;            ret+=f;            if(ret==maxflow) return ret;        }    }    return ret;}void Dinic(){    int ans=0;    while(makedep()==1)    {        ans+=dfs(ss,INF,tt);    }    printf("%d\n",sum-ans);}void solve(){    for(int i=1; i<=n; i++)    {        for(int j=1; j<=n; j++)        {            if((j+i)%2==0)            {                add(ss,(i-1)*n+j,mp[i][j]);                add((i-1)*n+j,ss,0);            }            else            {                add((i-1)*n+j,tt,mp[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;            else            {                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 main(){    while(~scanf("%d",&n))    {        cnt=0;        memset(head,-1,sizeof(head));        ss=n*n+1;        tt=ss+1;        sum=0;        for(int i=1; i<=n; i++)        {            for(int j=1; j<=n; j++)            {                scanf("%d",&mp[i][j]);                sum+=mp[i][j];            }        }        solve();        Dinic();    }    return 0;}
阅读全文
0 0
原创粉丝点击