HDU 1565 方格取数(1)(最大独立点权覆盖 | 最小割)
来源:互联网 发布:铝箔保护层工程量算法 编辑:程序博客网 时间:2024/05/17 15:16
该题是一道经典的求最大点权独立集问题的题目 。 关于定义我就不多说了 。 说一下几个重要的关系 :
1.最大流 = 最小割 = 最小点权覆盖集 = sum - 最大点权独立集 。
因此,该题其实还可以用最小割来做,思想是相同的 。
因为我们不能取相邻的数字,所以很容易联想到最小割 。
那么我们可以先给每个格子编号1或2,形成二分图。 然后由1到2连边 。容量INF,与源点和汇点相连的容量为对应点的值。
这样,求得的最大流也是最小割。 最大点权独立集 = sum - 最小割 。
需要注意的是:上述的一切都是基于这样一个事实:图是二分图 。因此我们必须要构建一个单向连通的图,不能产生自环,这个在建图的时候要重视,不然会莫名WA 。
细节参见代码:
#include<bits/stdc++.h>using namespace std;const int maxn = 20*20*2;typedef long long ll;const int INF = 1000000000;int T,n,m,id1[55][55],id2[55][55];struct Edge { int from, to, cap, flow;};bool operator < (const Edge& a, const Edge& b) { return a.from < b.from || (a.from == b.from && a.to < b.to);}struct Dinic { int n, m, s, t; vector<Edge> old; vector<Edge> edges; // 边数的两倍 vector<int> G[maxn]; // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号 bool vis[maxn]; // BFS使用 int d[maxn]; // 从起点到i的距离 int cur[maxn]; // 当前弧指针void init(int n) { for(int i = 0; i < n; i++) G[i].clear(); edges.clear();}void AddEdge(int from, int to, int cap) { edges.push_back((Edge){from, to, cap, 0}); edges.push_back((Edge){to, from, 0, 0}); m = edges.size(); G[from].push_back(m-2); G[to].push_back(m-1);}bool BFS() { memset(vis, 0, sizeof(vis)); queue<int> Q; Q.push(s); vis[s] = 1; d[s] = 0; while(!Q.empty()) { int x = Q.front(); Q.pop(); for(int i = 0; i < G[x].size(); i++) { Edge& e = edges[G[x][i]]; if(!vis[e.to] && e.cap > e.flow) { vis[e.to] = 1; d[e.to] = d[x] + 1; Q.push(e.to); } } } return vis[t];}int DFS(int x, int a) { if(x == t || a == 0) return a; int flow = 0, f; for(int& i = cur[x]; i < G[x].size(); i++) { Edge& e = edges[G[x][i]]; if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) { e.flow += f; edges[G[x][i]^1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow;}int Maxflow(int s, int t) { this->s = s; this->t = t; int flow = 0; while(BFS()) { memset(cur, 0, sizeof(cur)); flow += DFS(s, INF); } return flow; }}g;int a[55][55];int dx[] = {0,1,0,-1};int dy[] = {1,0,-1,0};int main() { while(~scanf("%d",&n)) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&a[i][j]); int s[21][21] = {0}, sum = 0; s[1][1] = 1; g.init(n*n+5); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(s[i][j] == 1) { //编号,建立二分图 for(int k=0;k<4;k++) { int x = dx[k]+i, y = dy[k]+j; if(x < 1 || x > n || y < 1 || y > n || s[x][y] != 0) continue; s[x][y] = 2; } } else { for(int k=0;k<4;k++) { int x = dx[k]+i, y = dy[k]+j; if(x < 1 || x > n || y < 1 || y > n || s[x][y] != 0) continue; s[x][y] = 1; } } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { sum += a[i][j]; if(s[i][j] == 1) { //由1集合的点向2集合的点连边 int id = (i-1)*n + j ; g.AddEdge(0,id,a[i][j]);//这样,最小割的意义就是割去1集合的点或割去2中的某点 for(int k=0;k<4;k++) { int x = dx[k]+i, y = dy[k]+j; if(x < 1 || x > n || y < 1 || y > n ) continue; g.AddEdge(id,(x-1)*n+y,INF); } } else { //不可反向连边,会形成环。 int id = (i-1)*n + j; g.AddEdge(id,n*n+1,a[i][j]); } } printf("%d\n",sum - g.Maxflow(0,n*n+1)); } return 0;}
1 0
- HDU 1565 方格取数(1)(最大独立点权覆盖 | 最小割)
- hdu 1565 方格取数(1)(最小割,最大点权独立集)
- hdu 1565 方格取数(1)(最小割--最大权独立点集)
- hdu 3657 最大点权独立集变形(方格取数的变形最小割,对于最小割建图很好的题)
- hdoj 1569 方格取数(2) 【最小割】 【最大点权独立集】
- loj6007「网络流 24 题」方格取数(最大点权独立集+最小割)
- HDU1569 方格取数(2)(最大点权独立集 + 最小点权覆盖集 = 总权和)
- HDU 1565 方格取数(1)(最小割-Dinic)
- hdu 1565 方格取数(1)(最小割)
- hdu 1569 方格取数 最大点权独立集(hdu 1565)
- HDU 1565 方格取数(1) 【最大点权独立集】
- hdu 1565 方格取数(1) 最大点权独立集 网络流
- HDU 1565 方格取数(1)(最大点权独立集)
- HDU 1565 方格取数(1) 二分图最大点权独立集
- HDU 1565 1569 方格取数(最大点权独立集)
- HDU 1565 方格取数(1)(最大独立点集)
- 方格取数 hdu 1565 最小割
- 【网络流第四弹】最大点权独立集 ——HDU 1565 方格取数(1)
- 原型和原型链详解
- CF-SDUT-3360-
- 大学入試改革―本当に実現できるのか
- Android加载大图Bitmap发生OOM(Out Of Memmory Error)解决方案
- 解决The Apache Axis2 Web service runtime in Tomcat v7.0 Server does not support the service project 问
- HDU 1565 方格取数(1)(最大独立点权覆盖 | 最小割)
- Butterknife使用(学习总结)
- hdu3336 Count the string(dp)
- Java拾遗-------多线程
- 11个PHP框架——Web开发人员最爱
- svn管理
- android 设置继承FragmentStatePagerAdapter(里面之间的传值)
- Classes and Objects
- Unable to add the follwing facets to project testAxis2: Axis2 Web Services Core, Axis2 Web Services