Hdu 1569 方格取数(2) (网络流最大点权独立集)
2013-03-03 21:19
531 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1569
思路:首先黑白染色,源点到黑点连条边,值为格子数值,然后白色点到汇点也连条这样的边,然后每个黑点对与其相连的白点连条无穷大的边,然后求个最小割,答案就是所有格子数值和减去这个最小割。
思路:首先黑白染色,源点到黑点连条边,值为格子数值,然后白色点到汇点也连条这样的边,然后每个黑点对与其相连的白点连条无穷大的边,然后求个最小割,答案就是所有格子数值和减去这个最小割。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int INF = 0x6fffffff ; //权值上限 const int MAXPT = 3000; //顶点数上限 const int MAXEG = 50000 ; //边数上限 const int MAXQUE = 10005 ; //队列长度 /* s = 1 ; // 源点 t = n ; // 汇点 */ class MNF_SAP { private: //int m,n; int s,t; int dis[MAXPT]; //距离标号 int pre[MAXPT]; //前置顶点 int flow[MAXPT]; //到当前点为止,所有弧的最小值 int curedge[MAXPT]; //当前弧cur int cnt[MAXPT]; //k标号出现次数 int queue[MAXQUE],front,rear; bool vis[MAXPT]; void BFS () { int i,u; memset(vis,false,sizeof(vis)); front=rear=0; dis[t]=0; vis[t]=true; queue[++rear]=t; while (front!=rear) { u=queue[(++front)%MAXQUE]; for (i=head[u];i!=0;i=edges[i].next) if (vis[edges[i].v]==false && !edges[i].cap) { dis[edges[i].v]=dis[u]+1; vis[edges[i].v]=true; queue[(++rear)%MAXQUE]=edges[i].v; } } for (i=1;i<=n;i++) cnt[dis[i]]++; } public: struct Node { int v,cap,next; Node(){} Node (int _v,int _cap,int _next) { v=_v; cap=_cap; next=_next; } }edges[MAXEG]; int n; //总节点数 int e; int head[MAXPT]; // MNF_SAP(){} // ~MNF_SAP(){} void init (int temp) //算法初始化 { n=temp; e=2; memset (head,0,sizeof(head)); } void Add (int u,int v,int cap) //始,终,量 { edges[e]=Node(v,cap,head[u]); head[u]=e++; edges[e]=Node(u,0,head[v]); head[v]=e++; } int SAP () { int u,v,i,maxflow=0; //总最大流 s=1; t=n; u=s; flow[s]=INF; for (i=1;i<=n;i++) curedge[i]=head[i]; //当前弧初始化 BFS (); cnt[0]=n; while (dis[s]<n) { for (i=curedge[u];i!=0;i=edges[i].next) //找允许弧 if (edges[i].cap && dis[edges[i].v]+1==dis[u]) break; if (i!=0) //存在允许弧 { curedge[u]=i; //设置当前弧 v=edges[i].v; if (edges[i].cap<flow[u]) flow[v]=edges[i].cap; else flow[v]=flow[u]; //标记当前顶点为止经过的最小弧 u=v; pre[v]=i; //前置顶点边号 if (u==t) { do { edges[pre[u]].cap-=flow[t]; //正向弧减a[t] edges[pre[u]^1].cap+=flow[t]; //通过异或操作找反向弧 u=edges[pre[u]^1].v; } while (u!=s); maxflow+=flow[t]; //memset(flow,0,sizeof(flow)); flow[s]=INF; } } else //不存在允许弧 { if (--cnt[dis[u]]==0) break; //间隙优化 dis[u]=n; curedge[u]=head[u]; for (i=head[u];i!=0;i=edges[i].next) if (edges[i].cap && dis[edges[i].v]+1<dis[u]) dis[u]=dis[edges[i].v]+1; //修改距离标号为 最小的非允许弧加1 cnt[dis[u]]++; if (u!=s) u=edges[pre[u]^1].v; } } return maxflow; } }; int m,n; MNF_SAP ob; int main() { while(scanf("%d%d",&m,&n)!=EOF) { ob.init(m*n+2); int s=1; //源点 int t=m*n+2; //汇点 int temp,sum=0; for (int i=1;i<=m;i++) for (int j=1;j<=n;j++) { scanf("%d",&temp); sum+=temp; if ((i+j)%2==0) { ob.Add (s,(i-1)*n+j+1,temp); if (i>1) //点不在第一行 ob.Add((i-1)*n+j+1,(i-2)*n+j+1,INF); if (j>1) //点不在第一列 ob.Add((i-1)*n+j+1,(i-1)*n+j,INF); if (i<m) //点不在最后一行 ob.Add((i-1)*n+j+1,i*n+j+1,INF); if (j<n) //点不在最后一列 ob.Add((i-1)*n+j+1,(i-1)*n+j+1+1,INF); } else ob.Add((i-1)*n+j+1,t,temp); } printf("%d\n",sum-ob.SAP()); } return 0; }
相关文章推荐
- 【网络流第五弹】最大点权独立集 ——HDU 1569 方格取数(2)
- 独立最小【网络流第五弹】最大点权独立集 ——HDU 1569 方格取数(2)
- hdu1569 方格取数(2) 最大点权独立集=总权和-最小点权覆盖集 (最小点权覆盖集=最小割=最大流)
- hdu 1569 方格取数 最大点权独立集(hdu 1565)
- HDU 1565 1569 方格取数(最大点权独立集)
- HDU 1569 方格取数(2)(最大点权独立集)
- HDU-1565,1569 最大点权独立集(网络流)
- HDU 1569 - 方格取数(2) 二分图最大点权独立集(构图最大流解)
- HDU 1569 方格取数(2) (二分图的最大点权独立集)
- 方格取数(2) HDU - 1569(二分图最大点权独立集)
- HDU 1569 方格取数(2) 黑白染色+最大点独立集(sap)
- hdu - 1565 方格取数(1) && 1569 方格取数(2) (最大点权独立集)
- hdu 1565 方格取数(2)(网络流之最大点权独立集)
- hdu 1565 方格取数(1) 最大点权独立集 网络流
- 二分图带权最大独立集 网络流解决 hdu 1569
- HDU 1565 1569 方格取数(最大点权独立集)
- hdu 1569 方格取数(2)--最大点权独立集-->最大流
- hdu 1565 方格取数(1) 最大点权独立集 网络流
- 二分图带权最大独立集 网络流解决 hdu 1569
- 网络流(最大流) HDU 1565 方格取数(1) HDU 1569 方格取数(2)