【hihocoder 1424】 Asa's Chess Problem(有源汇上下界网络流)
UVALive-7670
ICPC北京2016-C题 hihocoder 1424
题意
有个 \(N\times N\) 的棋盘,告诉你每个格子黑色(1)或白色(0),以及每对能相互交换的同行或同列格子,每个格子只在一对中,即共有\(N\times N /2\)对。求最少交换次数使得每行每列的黑格子总数满足给出的上下范围:若最终第i行,第j列分别有\(R[i],C[j]\)个黑格子,那么需要让\(Rl[i]\le R[i]\le Rh[i],Cl[j]\le C[i]\le Ch[j]\)。
如果不存在方案输出-1。
\(T\le 100,2\le N \le 50\)。
题解
判定给定行和列和的01矩阵的存在性可以用网络流来做,所以这题也可以联想到用网络流求解。
建图,建边费用默认0:
- 每一行为一个点,编号rID(i)
- 每一列为一个点,编号cID(i)
- 源点为s,汇点为t
- 第i行第j列为1,则连边rID(i)->cID(j),上下界都是1
- 连边s->rID(i),上下界就是该行的限制
- 连边cID(i)->t,上下界就是该列的限制
- (x1,y1)和(x2,y2)可以交换
- 如果是同色,没有意义,不用管;
- 如果不同色,假设(x1,y1)是1:
- 若同行:连边cID(y1)->cID(y2),上界1,下界0,费用1。
- 若同列:连边rID(x2)->rID(x1),上界1,下界0,费用1。
那么如果s到t存在可行流,就代表有解。最大流的最小费用就是最少交换次数。
现在有一个有源汇的带上下界的网络流,我们知道怎么求解无源汇的带上下界的网络流,怎么转化呢?先将有源汇变成无源汇循环流:连边t->s,上界INF,下界0。接着就是将无源汇的带上下界的网络流变成没有下界(其实是下界为0)的网络流:
- 添加超级源点S,超级汇点T
- 原图每条边容量=原来的上界-下界
- 原图每个点u,\(in\) 为流入的流量下界和,\(out\) 为流出的流量下界和
- \(in>out\),则连S->u,容量in-out
- \(in<out\),则连u->T,容量out-in
S到T跑最大流,如果最大流等于S的出边流量之和,那么就有解。因为要求最小费用,所以跑最小费用最大流。
另外看到的建图是:
- s->rID(i)或s->cID(i),上下界是初始的行和或列和
- rID(i)->t或sID(i)->t,上下界是给定的行和或列和的限制
- (x1,y1)和(x2,y2)可以交换,不同的地方就是同列时:连边rID(x1)->rID(x2)。
后面解法就相同了。。。
代码
#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof a)
#define rep(i,l,r) for(int i=0,ed=r;i<ed;++i)
const int INF = 0x3f3f3f3f;
const int N = 200;
const int M = 100001;
using namespace std;
namespace MinCostMaxFlow {
struct edge{int to,nxt,cap,flow,cost;}e[M];
int head[N],cnt;
int pre[N],dis[N];
bool vis[N];
void init(){
cnt=0;mem(head,-1);
}
void addEdge(int u,int v,int w,int c=0){
e[cnt]=(edge){v,head[u],w,0,c};head[u]=cnt++;
e[cnt]=(edge){u,head[v],0,0,-c};head[v]=cnt++;
}
bool spfa(int s,int t,int n){
queue<int>q;
rep(i,0,n)dis[i]=INF,vis[i]=0,pre[i]=-1;
dis[s]=0;vis[s]=1;q.push(s);
while(!q.empty()){
int u=q.front();q.pop();vis[u]=0;
for(int i=head[u];~i;i=e[i].nxt){
int v=e[i].to;
if(e[i].cap>e[i].flow && dis[v]>dis[u]+e[i].cost){
dis[v]=dis[u]+e[i].cost;pre[v]=i;
if(!vis[v]){vis[v]=1;q.push(v);}
}
}
}
if(pre[t]==-1)return 0;
return 1;
}
int solve(int s,int t,int n,int &cost){
int flow=0;
cost=0;
while(spfa(s,t,n)){
int Min=INF;
for(int i=pre[t];~i;i=pre[e[i^1].to])
if(Min>e[i].cap-e[i].flow)Min=e[i].cap-e[i].flow;
for(int i=pre[t];~i;i=pre[e[i^1].to])
e[i].flow+=Min,e[i^1].flow-=Min,cost+=e[i].cost*Min;
flow+=Min;
}
return flow;
}
}
int n;
int a[N][N];
int S=1,T=2,s=3,t=4;
int need;
int in[N];
void add(int u,int v,int w,int c=0){
if(u==S)need+=w;
if(!w)return;
MinCostMaxFlow::addEdge(u,v,w,c);
}
void init(){
MinCostMaxFlow::init();
need=0;
mem(in,0);
}
inline int rID(int row){
return row+t+1;
}
inline int cID(int col){
return col+t+1+n;
}
void build(int k){
if(in[k]>0)add(S,k,in[k]);
else add(k,T,-in[k]);
}
void solve(){
int ans;
int ok=need==MinCostMaxFlow::solve(S,T,cID(n-1)+1,ans);
printf("%d\n",ok?ans:-1);
}
int main(){
while(~scanf("%d",&n)){
init();
rep(i,0,n)rep(j,0,n){
scanf("%d",&a[i][j]);
if(a[i][j]){
--in[rID(i)];
++in[cID(j)];
}
}
rep(i,0,n){
int l,r;
scanf("%d%d",&l,&r);
add(s,rID(i),r-l);
in[rID(i)]+=l;in[s]-=l;
}
rep(i,0,n){
int l,r;
scanf("%d%d",&l,&r);
add(cID(i),t,r-l);
in[cID(i)]-=l;in[t]+=l;
}
rep(i,0,n)
rep(j,0,2)
build(j?rID(i):cID(i));
build(s);build(t);
add(t,s,INF);
rep(i,0,n*n/2){
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
--x1;--y1;--x2;--y2;
if(a[x1][y1]^a[x2][y2]){
if(x1==x2){
if(a[x1][y1])swap(y1,y2);
add(cID(y2),cID(y1),1,1);
}
else{
if(a[x1][y1])swap(x1,x2);
add(rID(x1),rID(x2),1,1);
}
}
}
solve();
}
return 0;
}
【hihocoder 1424】 Asa's Chess Problem(有源汇上下界网络流)的更多相关文章
- POJ 2396 Budget(有源汇上下界网络流)
Description We are supposed to make a budget proposal for this multi-site competition. The budget pr ...
- ACM-ICPC 2018 沈阳赛区网络预赛 F. Fantastic Graph (贪心或有源汇上下界网络流)
"Oh, There is a bipartite graph.""Make it Fantastic."X wants to check whether a ...
- ACM-ICPC 2018 沈阳赛区网络预赛 F Fantastic Graph(贪心或有源汇上下界网络流)
https://nanti.jisuanke.com/t/31447 题意 一个二分图,左边N个点,右边M个点,中间K条边,问你是否可以删掉边使得所有点的度数在[L,R]之间 分析 最大流不太会.. ...
- 【有源汇上下界费用流】BZOJ 3876 [Ahoi2014]支线剧情
题目链接: http://www.lydsy.com:808/JudgeOnline/problem.php?id=3876 题目大意: 给定一张拓扑图(有向无环图),每条边有边权,每次只能从第一个点 ...
- ZOJ1994有源汇上下界可行流
http://fastvj.rainng.com/contest/236779#problem/G Description: n 行 m 列 给你行和 与 列和 然后有Q个限制,表示特定单元格元素大小 ...
- bzoj千题计划159:bzoj2055: 80人环游世界(有源汇上下界可行最小费用流)
http://www.lydsy.com/JudgeOnline/problem.php?id=2055 某个国家必须经过vi次, 可以转化为上下界都为vi的边 对这张图做有源汇上下界可行最小费用流 ...
- zoj 3229 Shoot the Bullet(有源汇上下界最大流)
Shoot the Bullethttp://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3442 Time Limit: 2 Second ...
- Shoot the Bullet(ZOJ3229)(有源汇上下界最大流)
描述 ensokyo is a world which exists quietly beside ours, separated by a mystical border. It is a utop ...
- 【有源汇上下界最大流】ZOJ 3229 Shoot the Bullet
题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3229 题目大意: n天给m个女孩拍照(1<=n<= ...
随机推荐
- Latex(表格|图片(一丢丢))
目录 普通的例子 Notation 例子 p{width} 列分割符 @{} \multicolumn supertabular | longtabular 浮动体 table 浮动体 图片 \use ...
- 《梦断代码》Scott Rosenberg著(二)
书中有一段说的是一个闪烁缺陷——在改变某软件中某个窗体的尺寸时,屏幕会闪烁一秒钟左右.虽然该缺陷不会影响程序运行,但它不符合作者的审美观,历时六个多月仍然没能修正.其实在日常的编程中也有许多小bug的 ...
- MyBatis模糊查询不报错但查不出数据的一种解决方案
今天在用MyBatis写一个模糊查询的时候,程序没有报错,但查不出来数据,随即做了一个测试,部分代码如下: @Test public void findByNameTest() throws IOEx ...
- 福州大学软件工程1816 | W班 第10次作业[软件工程实践总结]
作业链接 个人作业--软件工程实践总结 评分细则 本次由五个问题(每个十分)+创意照片(五分)+附加题(十分)组成 评分统计图 千帆竞发图 汇总成绩排名链接 汇总链接
- shell脚本--CGI获取请求数据(GET / POST)
Case 1: 获取地址栏传递的参数(即通过GET方式) CGI的环境变量中有个QUERY_STRING,可以获取地址栏传递的参数,该参数可以是手动加上的,也可以是通过表单的get方式提交的,比如下面 ...
- 安全测试学习之bWAPP环境搭建
安装环境:window7+IIS+mysql+php bWAPP下载地址:https://sourceforge.net/projects/bwapp/files/bee-box/ ,直接点击Dow ...
- vsconsole
一.安装 npm install vconsole 二. if (process.env.NODE_ENV === `development`) { const { logger } = requir ...
- C#复习笔记(2)--C#1所搭建的核心基础
通过对C#1所搭建的核心基础的深入了解,可以知道之后的C#版本在C#1的基础上做了很多扩展,而这些扩展都是基于C#搭建的核心基础而来的. 委托 一.编写委托的过程 委托经常和C语言的“函数指针”挂钩. ...
- day 7-13 数据库的数据类型
一. 数据类型 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的 注意:int类型的宽度是显示宽度,并非是数据的存储宽度 详细的介绍:http:// ...
- 刪除nodejs
https://www.cnblogs.com/fighxp/p/7410235.html https://www.cnblogs.com/fighxp/p/7411608.html