表示“必须选”的模型

题目大意


题目分析

一个格子有四种方式看上去很难处理。将横竖两个方向分开考虑,会发现:因为收益只与相邻格子是否连通有关,所以可以将一个格子拆成表示横竖两个方向的,互相独立的点。

上图的格子里四个方向红边表示的就是一个格子的可能方向;拆点后所连蓝边的容量为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的更多相关文章

  1. ICPC 2016 China Final J. Mr.Panda and TubeMaster【最大费用最大流】

    有一种限制下界强制选的,但是也可以不用 把每个格点拆成两个,一个连s一个连t,对于不是必选的连中间连流量1费用0边表示不选,然后黑白染色,黑点连横着白点连竖着,边权就是这条水管的权值,然后跑最大费用最 ...

  2. China Final J - Mr.Panda and TubeMaster

    和一般的管道不同 不能类似“无限之环”或者“弯弯国”的建图,因为这两个题都是某些位置必须有,或者必须没有 但是本题可以有的位置随意,不能限制某个位置要么流2,要么流0,(实际上可能流了1过去) 所以建 ...

  3. J - Mr.Panda and TubeMaster

    题解 我们可以把每个格子拆成两个点,一个表示横向的,一个表示纵向的,相邻的格子横向和纵向连边. 如果直接按照题意做的话,我们应当在横向和纵向的点之间连边,有限制的边设下界为1,然后跑可行流. 或者考虑 ...

  4. Gym101194J Mr.Panda and TubeMaster 二分图、费用流

    传送门 看到这张图,是一个网格图,而且有回路限制,不难想到黑白染色. 一般来说我们对一张图黑白染色之后都是黑色点向白色点连边,但是这道题往这边想似乎就想不出建图方法了,因为"一个格子强制流满 ...

  5. 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 ...

  6. 2016 China Final E - Bet

    /************************************************************************* > File Name: E.cpp > ...

  7. 2016 China Final H - Great Cells

    /************************************************************************* > File Name: H.cpp > ...

  8. 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 ...

  9. 2016 China Collegiate Programming Contest Final

    2016 China Collegiate Programming Contest Final Table of Contents 2016 China Collegiate Programming ...

随机推荐

  1. ubuntu18.04中mysql的安装及远程连接配置

    1.ubuntu 18.04 下mysql的安装 sudo apt install mysql-server 2.mysql 安装配置 sudo mysql_secure_installation 参 ...

  2. git小白的学习

    1.1 Git介绍 1.1.1 什么是Git Git是一个开源的分布式版本控制系统,可以有效.高速地处理从很小到非常大的项目版本管理.Git 是 Linus Torvalds 为了帮助管理 Linux ...

  3. Java获取路径

    "./" 代表当前目录,"../"代表上级目录 后续更新!!!

  4. B - Median Pyramid Easy 构造题

    B - Median Pyramid Easy Time limit : 2sec / Memory limit : 256MB Score : 400 points Problem Statemen ...

  5. Codeforces Round #377 (Div. 2) E. Sockets

    http://codeforces.com/contest/732/problem/E 题目说得很清楚,每个电脑去插一个插座,然后要刚好的,电脑的power和sockets的值相同才行. 如果不同,还 ...

  6. 六,IO系统

    六,IO系统 一,数据源 1,数据源--管道确认使用那根管道--节点流 2,先确定管道在tey中new出管道,new出后就写关闭代码,写完关闭代码在写中间代码 3,取数据和放数据结束语句必须有两个,不 ...

  7. Aspose.word直接转pdf

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

  8. nodejs模块学习: webpack

    nodejs模块学习: webpack nodejs 发展很快,从 npm 上面的包托管数量就可以看出来.不过从另一方面来看,也是反映了 nodejs 的基础不稳固,需要开发者创造大量的轮子来解决现实 ...

  9. webpack.config.js====webpack-dev-server开发服务器配置

    1. 安装webpack-dev-server(在指定目录下),一定要先安装完毕webpack webpack-cli之后在安装webpack-dev-server 一个基于expressjs的开发服 ...

  10. zuul prefix

    经过测试,书上应该是写错了,如果要全部的路由加前缀,需要将zuul.stripPrefix=true进行设置 而不是书上所说的false