【费用流】 ICPC 2016 China Final J. Mr.Panda and TubeMaster
表示“必须选”的模型
题目大意
题目分析
一个格子有四种方式看上去很难处理。将横竖两个方向分开考虑,会发现:因为收益只与相邻格子是否连通有关,所以可以将一个格子拆成表示横竖两个方向的,互相独立的点。
上图的格子里四个方向红边表示的就是一个格子的可能方向;拆点后所连蓝边的容量为1,费用即为连通两个格子的收益。
但是这样建图不能够表示某些格子必须要选。
考虑一个格子如果被选择了会发生什么:因为每个格子都处在环上,那么被选择的网格一定可以通过其他节点走到汇点。这意味着一个格子拆成的两个节点之间的边就可以先不建,而若最大流不等于网格总数,即有节点不可能被合法选中。
建图的时候一定要先理解清楚,因为有很多种错误方式,下图就是其中一个。
#include<queue>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
const int maxn = ;
const int maxm = ;
const int INF = 2e9; struct Edge
{
int u,v,f,c,cst;
Edge(int a=, int b=, int c=, int d=, int e=):u(a),v(b),f(c),c(d),cst(e) {}
}edges[maxm];
int sne,n,m,S,T;
bool ess[][],inq[maxn];
int tagl[][],tagr[][],valc[][],valr[][]; //tagl为入点,tagr为出点
int edgeTot,head[maxn],nxt[maxm],flw[maxn],cst[maxn],bck[maxn]; int read()
{
char ch = getchar();
int num = , fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = -;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
return num*fl;
}
void addedge(int u, int v, int c, int cst)
{
edges[edgeTot] = Edge(u, v, , c, cst), nxt[edgeTot] = head[u], head[u] = edgeTot++;
edges[edgeTot] = Edge(v, u, , , -cst), nxt[edgeTot] = head[v], head[v] = edgeTot++;
}
void maxFlow()
{
int mxFlw = , cost = ;
for (;;)
{
std::queue<int> q;
memset(flw, , sizeof flw);
memset(bck, , sizeof bck);
memset(cst, 0x3f3f3f3f, sizeof cst);
q.push(S), flw[S] = INF, cst[S] = ;
for (int tmp; q.size(); )
{
tmp = q.front(), q.pop(), inq[tmp] = ;
for (int i=head[tmp]; i!=-; i=nxt[i])
{
int v = edges[i].v;
if (cst[tmp]+edges[i].cst < cst[v]&&edges[i].f < edges[i].c){
bck[v] = i, cst[v] = cst[tmp]+edges[i].cst;
flw[v] = std::min(flw[tmp], edges[i].c-edges[i].f);
if (!inq[v]) inq[v] = , q.push(v);
}
}
}
if (!flw[T]) break;
for (int i=T; i!=S; i=edges[bck[i]].u)
edges[bck[i]].f += flw[T], edges[bck[i]^].f -= flw[T];
mxFlw += flw[T], cost += cst[T]*flw[T];
}
if (mxFlw!=n*m) puts("Impossible");
else printf("%d\n",-cost);
}
int main()
{
sne = read();
for (int cse=; cse<=sne; cse++)
{
printf("Case #%d: ",cse);
memset(ess, , sizeof ess);
memset(head, -, sizeof head);
edgeTot = , n = read(), m = read();
for (int i=; i<=n; i++)
for (int j=; j<m; j++)
valc[i][j] = read();
for (int i=; i<n; i++)
for (int j=; j<=m; j++)
valr[i][j] = read();
for (int i=, cnt=; i<=n; i++)
for (int j=; j<=m; j++)
tagl[i][j] = ++cnt, tagr[i][j] = ++cnt;
S = , T = tagr[n][m]+;
for (int i=; i<=n; i++)
for (int j=; j<=m; j++)
if ((i+j)&){ //为避免重复建边的处理技巧
if (j+ <= m) addedge(tagl[i][j], tagr[i][j+], , -valc[i][j]);
if (j- >= ) addedge(tagl[i][j], tagr[i][j-], , -valc[i][j-]);
}else{
if (i+ <= n) addedge(tagl[i][j], tagr[i+][j], , -valr[i][j]);
if (i+ >= ) addedge(tagl[i][j], tagr[i-][j], , -valr[i-][j]);
}
for (int i=read(); i; i--) ess[read()][read()] = ;
for (int i=; i<=n; i++)
for (int j=; j<=m; j++)
{
addedge(S, tagl[i][j], , );
addedge(tagr[i][j], T, , );
if (!ess[i][j]) addedge(tagl[i][j], tagr[i][j], , );
}
maxFlow();
}
return ;
}
END
【费用流】 ICPC 2016 China Final J. Mr.Panda and TubeMaster的更多相关文章
- ICPC 2016 China Final J. Mr.Panda and TubeMaster【最大费用最大流】
有一种限制下界强制选的,但是也可以不用 把每个格点拆成两个,一个连s一个连t,对于不是必选的连中间连流量1费用0边表示不选,然后黑白染色,黑点连横着白点连竖着,边权就是这条水管的权值,然后跑最大费用最 ...
- China Final J - Mr.Panda and TubeMaster
和一般的管道不同 不能类似“无限之环”或者“弯弯国”的建图,因为这两个题都是某些位置必须有,或者必须没有 但是本题可以有的位置随意,不能限制某个位置要么流2,要么流0,(实际上可能流了1过去) 所以建 ...
- J - Mr.Panda and TubeMaster
题解 我们可以把每个格子拆成两个点,一个表示横向的,一个表示纵向的,相邻的格子横向和纵向连边. 如果直接按照题意做的话,我们应当在横向和纵向的点之间连边,有限制的边设下界为1,然后跑可行流. 或者考虑 ...
- Gym101194J Mr.Panda and TubeMaster 二分图、费用流
传送门 看到这张图,是一个网格图,而且有回路限制,不难想到黑白染色. 一般来说我们对一张图黑白染色之后都是黑色点向白色点连边,但是这道题往这边想似乎就想不出建图方法了,因为"一个格子强制流满 ...
- 2016 ACM-ICPC China Finals #F Mr. Panda and Fantastic Beasts
题目链接$\newcommand{\LCP}{\mathrm{LCP}}\newcommand{\suf}{\mathrm{suf}}$ 题意 给定 $n$ 个字符串 $s_1, s_2, \dots ...
- 2016 China Final E - Bet
/************************************************************************* > File Name: E.cpp > ...
- 2016 China Final H - Great Cells
/************************************************************************* > File Name: H.cpp > ...
- 2016EC Final F.Mr. Panda and Fantastic Beasts
题目大意 \(T(1\leq T\leq42)\)组数据,给定\(n(2\leq n\leq 50000)\)个字符串\(S_{i}(n\leq\sum_{i=1}^{n}S_{i}\leq 2500 ...
- 2016 China Collegiate Programming Contest Final
2016 China Collegiate Programming Contest Final Table of Contents 2016 China Collegiate Programming ...
随机推荐
- BZOJ 4668: 冷战 并查集&&暴力LCA(雾)
利用并查集按秩合并,保存每个点合并的时间: 求时间时,就一直跳u=fa[u],并记录路径上时间的最大值,代表最后一次合并的时间 #include<cstdio> #include<i ...
- 查询索引range失效
在某一个时间字段加索引,短的时间范围内查询,索引生效,为range.长时间范围,索引失效,查全表. 当索引查的数据量超过全表30%的数据,索引失效,会查全表.
- C语言-字符操作函数
1字符数组的初始化: 1.1 char string={'c','h','i','n','a'} 1.2char string={"china"}或者去掉{}即char strin ...
- 1137 - Sin your life sin公式 + 枚举
http://www.ifrog.cc/acm/problem/1137 和差化积公式, 变成2 * sin((x + y) / 2) * cos((x - y) / 2) + sin(n - (x ...
- MYSQL查询~ 存在一个表而不在另一个表中的数据
A.B两表,找出ID字段中,存在A表,但是不存在B表的数据.A表总共13w数据,去重后大约3W条数据,B表有2W条数据,且B表的ID字段有索引. 方法一 使用 not in ,容易理解,效率低 ~执 ...
- oracle备份imp命令大全
oracle中imp命令详细解释 Oracle的导入有用程序(Import utility)同意从数据库提取数据,而且将数据写入操作系统文件.imp使用的基本格式:imp[username[/pass ...
- Runner启动器
Runner启动器的两种创建方式: 实现ApplicationRunner接口,复写run()方法 实现CommandLineRunner接口,复写run()方法 Runner启动器的执行顺序 如果一 ...
- vuejs 组件 移动端push 没有渲染页面
this.idcards.push(arr) 这个无效 就知道了 vuejs有个跟push相同的方法 console.log(this.list.push.toString()) 这个push是个同名 ...
- ABAP区别CLEAR、REFRESH、FREE
CLEAR.REFRESH.FREE 内表:如果使用有表头行的内表,CLEAR 仅清除表格工作区域.例如 clear gs-school 清除工作区. 要重置整个内表而不清除表格工作区域,使用REFR ...
- (2017.10.16) javascript 数据类型转换与操作
javascript 有 5 种基本数据类型:undefined.null.Boolean.String.Number,还有1 种较复杂的数据类型 Object:各种类型之间可以相互转换,其中有些有趣 ...