题目链接: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. 【搜索】POJ-3187 枚举全排列

    一.题目 Description FJ and his cows enjoy playing a mental game. They write down the numbers from 1 to ...

  2. Software Defined Networking(Week 2, part 3)

    Control of Packet-switch Network 我们已经讨论过中心控制网络的原理,但主要是以电话网络做模型的.现在我们来看看对于分组交换网络的控制是如何改进的. Why Separa ...

  3. PyCharm 配置远程python解释器和在本地修改服务器代码

    PyCharm 配置远程python解释器和在本地修改服务器代码 最近在学习机器学习的过程中,常常需要将本地写的代码传到GPU服务器中,然后在服务器上运行.之前的做法一直是先在本地写好代码,然后通过F ...

  4. 10th 本周工作量及进度统计

    本周PSP C(类别) C(内容) S(开始时间) ST(结束时间) I(中断时间) T(实际时间) 文档 11月22日 规格说明书练习 10:23­ 15:30 132 175 11月23日 知识点 ...

  5. docker搭建redis未授权访问漏洞环境

    这是redis未授权访问漏洞环境,可以使用该环境练习重置/etc/passwd文件从而重置root密码 环境我已经搭好放在了docker hub 可以使用命令docker search ju5ton1 ...

  6. 红帽旗下Linux的版本说明RedHat、CentOS、Fedora、OEL等

    简单总结一下RedHat.CentOS.Fedora Core区别关系: RedHat: 红帽已经被IBM 340亿刀收购了,但是红帽依旧发型自己的RedHat enterprise linux 版本 ...

  7. Windows 作为 openssl server端时的处理

    1. 跟上一个博客一样, 下载openssh 然后安装时 同时选择 server端. 2. 安装时设置密码 其他默认即可 3. xshell 创建连接. 注意 我使用的是 administrator ...

  8. Majority Number III

    Given an array of integers and a number k, the majority number is the number that occursmore than 1/ ...

  9. Best Time to Buy and Sell Stock IV

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  10. poj 1523 SPF(双连通分量割点模板)

    题目链接:http://poj.org/problem?id=1523 题意:给出无向图的若干条边,求割点以及各个删掉其中一个割点后将图分为几块. 题目分析:割点用tarjan算法求出来,对于每个割点 ...