题目链接:http://codeforces.com/gym/101149/problem/D

题目大意:

堡垒受到攻击。堡垒是n*m的矩阵,矩阵里刚开始都是平地,然后那个数值表示在当前平地上建一面墙需要a[i][j]的时间。目前我们在位置(r, c),我们找一种方法,把(r,c)全部围起来需要的最短时间?

思路:拆点,拆成in和out两个,in和out之间的cap就是a[i][j],然后就是简单的建边拉。

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n") const int maxn = * * + ;
const int INF = 0x3f3f3f3f;
struct Edge {
int from, to, cap, flow;
}; struct Dinic {
int n, m, s, t; ///节点的个数,边的编号,起点,终点
vector<Edge> edges; // 边数的两倍
vector<int> G[maxn]; // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
bool vis[maxn]; // BFS使用
int d[maxn]; // 从起点到i的距离
int cur[maxn]; // 当前弧指针
/////////蓝书363
int inq[maxn]; // 是否在队列中
int p[maxn]; // 上一条弧
int a[maxn]; //可改进量 void ClearAll(int n) {
this->n = n; ///这个赋值千万不能忘
for(int i = ; i < n; i++) G[i].clear();
edges.clear();
} void ClearFlow() { ///清除流量,例如蓝书368的UVA11248里面的优化,就有通过清除流量来减少增广次数的
for(int i = ; i < edges.size(); i++) edges[i].flow = ;
} void Reduce() {///直接减少cap,也是减少增广次数的
for(int i = ; i < edges.size(); i++) edges[i].cap -= edges[i].flow;
} void AddEdge(int from, int to, int cap) {
edges.push_back((Edge){from, to, cap, });
edges.push_back((Edge){to, from, , });
m = edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
} bool BFS() {///bfs构建层次图
memset(vis, , sizeof(vis));
queue<int> Q;
Q.push(s);
vis[s] = ;
d[s] = ;
while(!Q.empty()) {
int x = Q.front(); Q.pop();
for(int i = ; i < G[x].size(); i++) {
Edge& e = edges[G[x][i]];
if(!vis[e.to] && e.cap > e.flow) {//只考虑残量网络中的弧
vis[e.to] = ;
d[e.to] = d[x] + ;
Q.push(e.to);
}
}
}
return vis[t];
} int DFS(int x, int a) {///a表示目前为止,所有弧的最小残量。但是也可以用它来限制最大流量,例如蓝书368LA2957,利用a来保证增量,使得最后maxflow=k
if(x == t || a == ) return a;
int flow = , f;
for(int& i = cur[x]; i < G[x].size(); i++) {//从上次考虑的弧,即已经访问过的就不需要在访问了
Edge& e = edges[G[x][i]];
if(d[x] + == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > ) {
e.flow += f;
edges[G[x][i]^].flow -= f;
flow += f;
a -= f;
if(a == ) break;//如果不在这里终止,效率会大打折扣
}
}
return flow;
}
/**最大流*/
int Maxflow(int s, int t) {
this->s = s; this->t = t;
int flow = ;
while(BFS()) {
memset(cur, , sizeof(cur));
flow += DFS(s, INF);///这里的INF可以发生改变,因为INF保证的是最大残量。但是也可以通过控制残量来控制最大流
}
return flow;
} /**最小割*/
char ch[maxn][maxn];
void Mincut(int x, int y) { /// call this after maxflow求最小割,就是S和T中还存在流量的东西
BFS();///重新bfs一次
for (int i = ; i < x; i++)
for (int j = ; j < y; j++)
ch[i][j] = '.';
int cnt = ;
for(int i = ; i < edges.size(); i++) {
Edge& e = edges[i];
if(vis[e.from] && !vis[e.to] && e.cap >= && e.to - e.from == x * y) {///这里和ISAP不一样
cnt++;
int nx = e.from / y, ny = e.from - nx * y;
ch[nx][ny] = 'X';
//printf("e.from = %d e.to = %d nx = %d ny = %d\n", e.from, e.to, nx, ny);
}
}
//printf("cnt = %d\n", cnt);
for (int i = ; i < x; i++){
for (int j = ; j < y; j++){
printf("%c", ch[i][j]);
}
cout << endl;
} } void debug(){///debug
for (int i = ; i < edges.size(); i++){
printf("u = %d v = %d cap = %d flow = %d\n", edges[i].from + , edges[i].to + , edges[i].cap, edges[i].flow);
}
}
};
Dinic g; int n, m, a, b;
int atlas[maxn][maxn]; int dx[] = {, -, , };
int dy[] = {, , , -};
int in_id(int x, int y){
return x * m + y;
}
int out_id(int x, int y){
return n * m + x * m + y;
} int main(){
scanf("%d%d%d%d", &n, &m, &a, &b);
a--, b--;
for (int i = ; i < n; i++){
for (int j = ; j < m; j++){
scanf("%d", &atlas[i][j]);
}
}
int s = in_id(a, b), t = n * m * + ;
g.ClearAll(t);
for (int i = ; i < n; i++){
for (int j = ; j < m; j++){
if (a == i && b == j) {
for (int k = ; k < ; k++){
int nx = i + dx[k], ny = j + dy[k];
if (nx < || ny < || nx >= n || ny >= m) continue;
g.AddEdge(in_id(i, j), in_id(nx, ny), INF);
}
continue;
}
else {
g.AddEdge(in_id(i, j), out_id(i, j), atlas[i][j]);
if (i == || j == || i == n- || j == m-)
g.AddEdge(out_id(i, j), t, INF);
}
for (int k = ; k < ; k++){
int nx = i + dx[k], ny = j + dy[k];
if (nx < || ny < || nx >= n || ny >= m) continue;
if (nx == a && ny == b) continue;
g.AddEdge(out_id(i, j), in_id(nx, ny), INF);
}
}
}
printf("%d\n", g.Maxflow(s, t));
g.Mincut(n, m);
return ;
}

最小割 D. Behind the Wall Samara University ACM ICPC 2016-2017 Quarterfinal Qualification Contest的更多相关文章

  1. 几何+思维 Samara University ACM ICPC 2016-2017 Quarterfinal Qualification Contest K. Revenge of the Dragon

    题目链接:http://codeforces.com/gym/101149/problem/K 题目大意: 给你两个点a,b.一个人在a点,一个人在b点,b点的人要追杀a的点,他的跑步速度是a的两倍. ...

  2. 最短路+找规律 Samara University ACM ICPC 2016-2017 Quarterfinal Qualification Contest L. Right Build

    题目链接:http://codeforces.com/gym/101149/problem/L 题目大意:有n个点(其实是n+1个点,因为编号是0~n),m条有向边.起点是0,到a和b两个节点,所经过 ...

  3. 贪心+离散化+线段树上二分。。。 Samara University ACM ICPC 2016-2017 Quarterfinal Qualification Contest G. Of Zorcs and Axes

    题目链接:http://codeforces.com/gym/101149/problem/G 题目大意:给你n对数字,为(a[i], b[i]),给你m对数字,为(w[i], c[i]).给n对数字 ...

  4. 训练报告 (2014-2015) 2014, Samara SAU ACM ICPC Quarterfinal Qualification Contest

    Solved A Gym 100488A Yet Another Goat in the Garden   B Gym 100488B Impossible to Guess Solved C Gym ...

  5. 【最小割】【Dinic】HihoCoder - 1252 - The 2015 ACM-ICPC Asia Beijing Regional Contest - D - Kejin Game

    题意:有一个技能学习表,是一个DAG,要想正常学习到技能x,要将指向x的技能全部先学到,然后会有一个正常花费cx.然后你还有一种方案,通过氪金dx直接获得技能x.你还可以通过一定的代价,切断一条边.问 ...

  6. Samara SAU ACM ICPC 2013-2014 Quarterfinal Qualification Contest

    A: 简单题,因为题目中说了不会有数据相同: #include<cstdio> #include<algorithm> #define maxn 200005 using na ...

  7. sdut 2162:The Android University ACM Team Selection Contest(第二届山东省省赛原题,模拟题)

    The Android University ACM Team Selection Contest Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里 ...

  8. Golden Eggs HDU - 3820(最小割)

    Golden Eggs Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  9. BZOJ 1391: [Ceoi2008]order [最小割]

    1391: [Ceoi2008]order Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1509  Solved: 460[Submit][Statu ...

随机推荐

  1. 0428-Scrum团队成立

    ------------------------------3.0------------------------------------------ 一.项目要求 5.Scrum团队成立 5.1 团 ...

  2. sqlserver 修改表字段长度

    ALTER TABLE Table1 ALTER COLUMN column1 VARCHAR(255)

  3. Idea安装Python插件并配置Python SDK

    第一步:在help/about中查看IDEA版本,作者IDEA 15.0.2 第二步:在http://plugins.jetbrains.com/plugin/631中下载python-143.116 ...

  4. js对数组进行浅复制,深复制的方法

    js 数组常用方法,数组的拷贝(不影响原数组),数组相等 置顶2017年07月17日 17:39:26 阅读数:4640 改变原数组的方法: pop();删除尾部的第一个元素并且返回这个元素: var ...

  5. php $_SERVER['HTTP_USER_AGENT'] 2

    //mobile  false pc   true no pc    function is_mobile(){        $agent = strtolower($_SERVER['HTTP_U ...

  6. 多示例学习 multiple instance learning (MIL)

    多示例学习:包(bags) 和 示例 (instance). 包是由多个示例组成的,举个例子,在图像分类中,一张图片就是一个包,图片分割出的patches就是示例.在多示例学习中,包带有类别标签而示例 ...

  7. P1503 鬼子进村

    题目背景 小卡正在新家的客厅中看电视.电视里正在播放放了千八百次依旧重播的<亮剑>,剧中李云龙带领的独立团在一个县城遇到了一个鬼子小队,于是独立团与鬼子展开游击战. 题目描述 描述 县城里 ...

  8. Ubuntu实用软件安装[转]

    Gedit编辑器配置 Ubuntu14.04从安装软件到卸载软件,删除安装包 linux wget 命令用法详解(附实例说明) ==================================== ...

  9. 【转】高手带你深入理解ucos任务堆栈

    首先,我们来理解一下两个概念: 1.堆栈就是一段连续的空间.用于存储数据的,在c计算机中有很多应用,比如发生中断时保存现场,c语言函数调用时保存现场和临时变量. 2.堆栈指针就是一个数据指针.有时候计 ...

  10. P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold 解题报告

    P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold 题意 给一个字符串,每次可以从两边中的一边取一个字符,要求取出的字符串字典序最小 可以Hash+二分 也可以S ...