BZOJ 1475 最小割 解题报告

来源:互联网 发布:淘宝儿童电动车 编辑:程序博客网 时间:2024/05/29 09:33

1475: 方格取数

Description

在一个n*n的方格里,每个格子里都有一个正整数。从中取出若干数,使得任意两个取出的数所在格子没有公共边,且取出的数的总和尽量大。

Input

第一行一个数n;(n<=30) 接下来n行每行n个数描述一个方阵

Output

仅一个数,即最大和

Sample Input

2
1 2
3 5

Sample Output

6

【解题报告】

代码如下:

/**************************************************************    Problem: 1475    User: onepointo    Language: C++    Result: Accepted    Time:124 ms    Memory:2164 kb****************************************************************/#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;#define inf 0x3f3f3f3f#define N 10010#define M 100010int cnt=-1,head[N];struct Edge{int to,nxt,f;}e[M];int vis[N],dis[N];int n,m,ss,tt;int mp[50][50],ans=0,mark[50][50];int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0};void adde(int u,int v,int c){    e[++cnt].to=v;e[cnt].f=c;    e[cnt].nxt=head[u];head[u]=cnt;    e[++cnt].to=u;e[cnt].f=0;    e[cnt].nxt=head[v];head[v]=cnt;}bool bfs(){    memset(dis,0,sizeof(dis));    memset(vis,0,sizeof(vis));    queue <int> q;    vis[ss]=1;q.push(ss);    while(!q.empty())    {        int u=q.front();q.pop();        for(int i=head[u];~i;i=e[i].nxt)        {            int v=e[i].to;            if(e[i].f&&!vis[v])            {                q.push(v);vis[v]=1;                dis[v]=dis[u]+1;            }        }    }    return vis[tt];}int dfs(int u,int delta){    if(u==tt) return delta;    int ret=0;    for(int i=head[u];delta&&~i;i=e[i].nxt)    {        int v=e[i].to;        if(e[i].f&&dis[v]==dis[u]+1)        {            int flow=dfs(v,min(e[i].f,delta));            e[i].f-=flow;            e[i^1].f+=flow;            delta-=flow;            ret+=flow;        }    }    return ret;}int Dinic(){    int ret=0;    while(bfs()) ret+=dfs(ss,inf);    return ret;}bool pd(int x,int y){    if(x<1||y<1||x>n||y>n) return 0;    return 1;}int main(){//  freopen("in","r",stdin);    memset(head,-1,sizeof(head));    scanf("%d",&n);    ss=0,tt=n*n+1;    int w=(n*n+1)/2,b=0;    for(int i=1;i<=n;++i)    for(int j=1;j<=n;++j)    {        if((i+j)%2==0) b++,mark[i][j]=b;        else w++,mark[i][j]=w;          scanf("%d",&mp[i][j]);        ans+=mp[i][j];    }    for(int i=1;i<=n;++i)    for(int j=1;j<=n;++j)    {        if((i+j)%2==0)        {            adde(0,mark[i][j],mp[i][j]);            for(int k=0;k<4;k++)                if(pd(i+xx[k],j+yy[k]))                    adde(mark[i][j],mark[i+xx[k]][j+yy[k]],inf);        }        else adde(mark[i][j],tt,mp[i][j]);      }    printf("%d",ans-Dinic());    return 0;}
原创粉丝点击