hdu acm 1565 方格取数(1)

来源:互联网 发布:黑莓passport删除软件 编辑:程序博客网 时间:2024/06/07 07:57

方格取数(1)

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7386    Accepted Submission(s): 2806


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

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

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

Sample Input
375 15 21 75 15 28 34 70 5
 

Sample Output
188
 解题关键:黑白染色。(横纵坐标相加分成奇,偶两部分),构造超级源点,汇点。原点到奇数点的权值为该点上的值,奇数点到相邻点的权值为INF,偶数点到汇点的权值为该点的值。求最小割。
最小割=最大流。
ans=总数的和-最小割。
#include <iostream>#include<string.h>using namespace std;#include<queue>#define INF 0x7fffffff#define MS(a,b) memset(a,b,sizeof(a))int mat[505][505],n,s,t,dis[300000],f,head[500005];#define MAXN 3000#include<algorithm>struct node{    int to,next,w;}edge[500005];void add(int u,int v,int w){    edge[f].to=v;    edge[f].next=head[u];    edge[f].w=w;    head[u]=f++;    edge[f].to=u;    edge[f].w=0;    edge[f].next=head[v];    head[v]=f++;}int bfs(){  int i,x,v;  MS(dis,-1);  dis[s]=0;  queue<int>q;  q.push(s);  while(!q.empty())  {    x=q.front();    q.pop();    for(i=head[x];i!=-1;i=edge[i].next)    {  v=edge[i].to;      if(edge[i].w&&dis[v]==-1)      {          dis[v]=dis[x]+1;          if(v==t)return 1;          q.push(v);      }    }  }  return 0;}int dfs(int s,int cur_flow){    int i,v,tmp,dt=cur_flow;//dt为当前剩余流量。    if(s==t)return cur_flow;    for(i=head[s];i!=-1;i=edge[i].next)    {       v=edge[i].to;       if(edge[i].w&&dis[s]==dis[v]-1)       {         int flow=dfs(v,min(dt,edge[i].w));//一条增广路,能够增广的流量,只能是路上最小流量边的流量               edge[i].w-=flow;//减少前向弧流量               edge[i^1].w+=flow;//增加后向弧流量               dt-=flow;//找到一条路,存起来       }    }    return cur_flow-dt;//一共增广的流量}int dinic(){  int ans=0;  while(bfs())    ans+=dfs(s,INF);  return ans;}int main(){   int i,j,sum,k,i1,j1;   while(cin>>n)   {       t=n*n+n+1;       f=sum=0;       s=1;   for(i=1;i<=n;i++)     for(j=1;j<=n;j++)    {      cin>>mat[i][j];      sum=sum+mat[i][j];    }     MS(head,-1);    for(i=1;i<=n;i++)      for(j=1;j<=n;j++)    {        if((i+j)%2==1)        {         add(1,i*n+j,mat[i][j]);         if(i+1<=n)             add(i*n+j,(i+1)*n+j,INF);         if(i-1>=1)             add(i*n+j,(i-1)*n+j,INF);         if(j+1<=n)             add(i*n+j,i*n+j+1,INF);         if(j-1>=1)             add(i*n+j,i*n+j-1,INF);         }          else           add(i*n+j,t,mat[i][j]);    }    cout<<sum-dinic()<<endl;    }    return 0;}


0 0