Hihocoder 1424 Asa's Chess Problem (有源汇上下界最小费用流)
来源:互联网 发布:windows错误恢复教程 编辑:程序博客网 时间:2024/06/16 07:32
Problem
Asa comes up with a chess problem. There are N×N chesses on a board with N×N grids, one chess in one grid. Some chesses are black while others are white.
The N×N grids are divided into (N×N) / 2 pairs(N is even), and each grid only belongs to one pair. The two grids of a pair are in the same row or the same column. We can swap the chesses in a pair of grids. Suppose the number of black chesses in row i is R[i], and the number of black chesses in column j is C[j]. The problem is whether there is a solution satisfy that Rl[i] <= R[i] <= Rh[i] and Cl[j] <= C[j] <= Ch[j]. Rl[i], Rh[i], Cl[j] and Ch[j] are constant integers.
Please calculate the minimum number of swaps Asa needed to make the chess board satisfy the restriction.
限制条件
最多 100 组样例
解题思路
有源汇的上下界最小费用流。
首先构造有上下界的图,定义源点 S 和 汇点 T 。
- 从 S 向每一行(编号 1~N)、每一列(编号 N+1~N+N)连一条有上下界的边,流量下界=流量上界=该行(列)的黑子个数。
- 从每一行向 T 连一条有上下界的边,流量下界为 Rl[i] ,上界为 Rh[i]
- 每一列类似
- 对于每一对 Pair,判断其是否同色,同色则对结果无影响,不考虑;不同色则判断其同行 OR 同列,同行则表示其交换对对应两列产生影响(对行无影响),从当前 pair 中代表黑子的列向代表白子的列连一条边,流量上下界分别为 0,1 。单位费用为 1 。同列类似。
此时问题可以看作求有源汇的上下界费用流求
求解有源汇上下界费用流可转换为求无源汇上下界最小费用可行循环流,通过
求解无源汇上下界最小费用可行循环流,重新构图:
- 在原基础上再新增一个超级源点 supS,supT,构造只有上界的网络。
- 对于原图的每一条边
(u, v) ,再新图中添加一条supS→v 流量为 u,v 流量下界的边。一条u→supT 流量为 u,v 流量下界的边,一条u→v 流量为 u,v流量上界-流量下界 的边。
做从
HINT: 原图中所有未提及的边费用都应记为 0 。新图中的重新构造的边的费用等同原图中对应边的费用。
代码
#include<bits/stdc++.h>using namespace std;const int N = 50 + 10;int n, chs[N][N], rl[N], rh[N], cl[N], ch[N], r[N], c[N], s, t, sups, supt, digflow;const int maxv = 100 + 10; //最大顶点数const int inf = 2e9; //应大于总费用和typedef pair<int, int> P; //first保存最短距离,second保存顶点编号struct Edge{ int to,cap,rev, cost;}e;vector<Edge> g[maxv]; //图的邻接表表示int h[maxv],dist[maxv]; //顶点的势、最短距离,若cost为整数,改INTint prevv[maxv],preve[maxv],V;//最短路中的前驱节点、对应的边、顶点数void addedge(int from, int to, int cap, int cost) { //加边 e.to = to, e.cap = cap, e.rev = g[to].size(), e.cost = cost; g[from].push_back(e); e.to = from, e.cap = 0, e.rev = g[from].size() - 1, e.cost = -cost; g[to].push_back(e);}void addedge(int from, int to, int low, int up, int cost) { digflow += low; addedge(sups, to, low, cost); addedge(from, supt, low, cost); addedge(from, to, up-low, cost);}int mincostflow(int s,int t,int f) { //求解从s到t,流量为f的最小费用流 int res = 0; memset(h,0,sizeof(4*t+4)); while(f>0) { priority_queue<P, vector<P>, greater<P> > que; fill(dist,dist+V,inf); dist[s] = 0; que.push(P(0,s)); while(!que.empty()) { P p = que.top(); que.pop(); int v = p.second; if(dist[v] < p.first) continue; for(int i=0;i<g[v].size();i++) { Edge &E = g[v][i]; if(E.cap > 0 && dist[E.to] > dist[v] + E.cost + h[v] - h[E.to]) { dist[E.to] = dist[v] + E.cost + h[v] - h[E.to]; prevv[E.to] = v; preve[E.to] = i; que.push(P(dist[E.to],E.to)); } } } if(dist[t] == inf) return -1; for(int v = 0;v < V;v++) h[v] += dist[v]; //沿s到t的最短路尽量增广 int d = f; for(int v = t;v!=s;v=prevv[v]) d = min(d,g[prevv[v]][preve[v]].cap); f -= d; res += h[t] * d; for(int v = t;v!=s;v=prevv[v]) { Edge &E = g[prevv[v]][preve[v]]; E.cap -= d; g[v][E.rev].cap += d; } } return res;}int main(){ while(scanf("%d", &n)!=EOF) { digflow = 0; s = 2*n + 1; sups = 0; t = 2*n + 2; supt = 2*n+3; memset(c, 0, sizeof(c)); memset(h, 0, sizeof(h)); for(int i=0;i<=supt;i++) g[i].clear(); int mx = 0; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d", &chs[i][j]); c[j] += chs[i][j]; h[i] += chs[i][j]; mx += chs[i][j]; } for(int i=1;i<=n;i++) { addedge(s, i, h[i], h[i], 0); addedge(s, i+n, c[i], c[i], 0); } for(int i=1;i<=n;i++) { scanf("%d %d", &rl[i], &rh[i]); addedge(i, t, rl[i], rh[i], 0); } for(int i=1;i<=n;i++) { scanf("%d %d", &cl[i], &ch[i]); addedge(i+n, t, cl[i], ch[i], 0); } for(int i=1, x1, y1, x2, y2;i<=n*n/2;i++) { scanf("%d %d %d %d", &x1, &y1, &x2, &y2); if(chs[x1][y1] == chs[x2][y2]) continue; if(chs[x1][y1] == 0) swap(x1, x2), swap(y1, y2); if(x1 == x2) { addedge(n+y1, n+y2, 1, 1); } else { addedge(x1, x2, 1, 1); } } addedge(t, s, mx, inf, 0); V = 2*n+4; int ans = mincostflow(sups, supt, digflow); printf("%d\n", ans); }}
- Hihocoder 1424 Asa's Chess Problem (有源汇上下界最小费用流)
- [acm/icpc2016北京赛区][hihocoder1424] Asa's Chess Problem 有上下界的费用流
- HihoCoder 1424Asa's Chess Problem
- hdu3157 有源汇上下界最小流
- [上下界有源汇最小费用可行流] BZOJ 3876: [Ahoi2014&Jsoi2014]支线剧情
- ★ SGU 176 有源汇上下界最小流
- HDU 3157 有源汇上下界最小流
- SGU 176 有源汇上下界最小流
- 有源汇的上下界最小流模板
- sgu176. Flow construction 有源汇上下界最小流
- 2502: 清理雪道 有源汇上下界最小流
- 【sgu176】Flow construction 有源汇上下界最小流
- SGU 176 有源汇上下界的最小流
- sgu 176 Flow construction(有源汇上下界最小流)
- HDU 3157 Crazy Circuits(有源汇上下界最小流)
- bzoj3876 [Ahoi2014&Jsoi2014]支线剧情(有源汇有上下界最小费用流)
- bzoj2055 80人环游世界(有源汇有上下界最小费用流)
- bzoj4213 贪吃蛇(二分图染色+有源汇有上下界最小费用流)
- 【java入门】使用选择法确定输入最大值
- The area
- dicom文件的传输语法讲解
- fabric源码解析4——配置系统
- C# 下载FTP服务器一个文件夹内的所有文件
- Hihocoder 1424 Asa's Chess Problem (有源汇上下界最小费用流)
- 复仇者vsX战警之训练
- Hbase面试问题
- python3.x和python2.x的translate与maketrans函数使用差异
- C#泛型约束
- 半个小时打造一部黑客手机,手把手教学,小学生坐在马桶上都能看得懂【一加手机 Nethunter】
- zxing实现二维码的生成和解析
- 利用scrapy爬取豆瓣top250
- Round 3 Bookshelf 2 POJ