Tile Cut~网络流入门题
Description
When Frodo, Sam, Merry, and Pippin are at the Green Dragon Inn drinking ale, they like to play a little game with parchment and pen to decide who buys the next round. The game works as follows: Given an m × n rectangular tile with each square marked with one of the incantations W, I, and N, find the maximal number of triominoes that can be cut from this tile such that the triomino has W and N on the ends and I in the middle (that is, it spells WIN in some order). Of course the only possible triominoes are the one with three squares in a straight line and the two ell-shaped ones. The Hobbit that is able to find the maximum number wins and chooses who buys the next round. Your job is to find the maximal number. Side note: Sam and Pippin tend to buy the most rounds of ale when they play this game, so they are lobbying to change the game to Rock, Parchment, Sword (RPS)!
Input
Each input file will contain multiple test cases. Each test case consists of an m × n rectangular grid (where 1 ≤ m, n ≤ 30) containing only the letters W, I, and N. Test cases will be separated by a blank line. Input will be terminated by end-of-file.
Output
For each input test case, print a line containing a single integer indicating the maximum total number of tiles that can be formed.
Sample Input
WIIW
NNNN
IINN
WWWI NINWN
INIWI
WWWIW
NNNNN
IWINN
Sample Output
5
5 以前一直不会网络流,直到现在遇到了网络流的题目才决定学一学。
这题就相当与我的网络流入门题吧。
这题其实是一个非常容易的网络流题目,只是我以前都不会。
所以觉得难,多看一些网络流的题目,多了解一些套路就可以了。
这里我用的是我的dinic模板。
现在自己仔细讲讲这题如何做,
题意:给你一张图,求出有几个WIN 。
网络流的难点就在构图上面,比较各种网络流模板差不多,都是当做
黑箱使用,如何构图就是一个艺术性的事情了。
其实这题类似于飞行员匹配问题,只是由两点匹配变成了三点匹配。
其实就是想办法转化为两点匹配,就是类似于二分图。
W是头,N是尾,所以主要处理的就是I,
主要说明一下构图原理,建立一个源点连接到所有的W,然后一个终点连接所有的N
这里最巧妙的就是in和out,
源点和out 【n*m,2*n*m-1】相连
终点和in 【0,n*m-1】 相连
所以这里处理I 就是将 I 作为连接 in 和 out 的桥梁
if (tu[i][j] == 'I') {
for (int k = 0 ; k < 4 ; k++) {
int nx = i + dx[k];
int ny = j + dy[k];
if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
if (tu[nx][ny] == 'W') f.add(nx * m + ny + out, i * n + j + in, 1) ;
if (tu[nx][ny] == 'N') f.add(i * m + j + out, nx * m + ny + in, 1) ;
}
}
这个就是核心代码了。
想必讲到这里 ,已经是非常非常详细了。
上代码
#include <vector>
#include <stdio.h>
#include <string>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;
const int maxn = 1e4 + ;
const int INF = 1e9 + ;
struct node {
int from, to, cap, flow;
};
struct Dinic {
int n, m, s, t;
vector<node>nodes;
vector<int>g[maxn];
int vis[maxn];
int d[maxn];
int cur[maxn];
void clearall(int n) {
for (int i = ; i < n ; i++) g[i].clear();
nodes.clear();
}
void clearflow() {
int len = nodes.size();
for (int i = ; i < len ; i++) nodes[i].flow = ;
}
void add(int from, int to, int cap) {
nodes.push_back((node) {
from, to, cap,
});
nodes.push_back((node) {
to, from, ,
});
m = nodes.size();
g[from].push_back(m - );
g[to].push_back(m - );
}
bool bfs() {
memset(vis, , sizeof(vis));
queue<int>q;
q.push(s);
d[s] = ;
vis[s] = ;
while(!q.empty()) {
int x = q.front();
q.pop();
int len = g[x].size();
for (int i = ; i < len ; i++) {
node &e = nodes[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) {
if (x == t || a == ) return a;
int flow = , f, len = g[x].size();
for (int &i = cur[x] ; i < len ; i++) {
node & e = nodes[g[x][i]];
if (d[x] + == d[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > ) {
e.flow += f;
nodes[g[x][i] ^ ].flow -= f;
flow += f;
a -= f;
if (a == ) break;
}
}
return flow;
}
int maxflow(int a, int b) {
s = a;
t = b;
int flow = ;
while(bfs()) {
memset(cur, , sizeof(cur));
flow += dfs(s, INF);
}
return flow;
}
vector<int>mincut() {
vector<int>ans;
int len = nodes.size();
for (int i = ; i < len ; i++) {
node & e = nodes[i];
if ( vis[e.from] && !vis[e.to] && e.cap > ) ans.push_back(i);
}
return ans;
}
void reduce() {
int len = nodes.size();
for (int i = ; i < len ; i++) nodes[i].cap -= nodes[i].flow;
}
} f;
int ans(vector<string> &tu ) {
int n = tu.size(), m = tu[].length();
int source = * n * m, sink = * n * m + ;
int in = , out = n * m;
int dx[] = {, , , -};
int dy[] = {, , -, };
f.clearall( * n * m + );
f.clearflow();
for (int i = ; i < n ; i++) {
for (int j = ; j < m ; j++) {
f.add(i * m + j + in, i * m + j + out, );
if (tu[i][j] == 'W') f.add(source, i * m + j + in, );
if (tu[i][j] == 'I') {
for (int k = ; k < ; k++) {
int nx = i + dx[k];
int ny = j + dy[k];
if (nx < || nx >= n || ny < || ny >= m) continue;
if (tu[nx][ny] == 'W') f.add(nx * m + ny + out, i * m + j + in, ) ;
if (tu[nx][ny] == 'N') f.add(i * m + j + out, nx * m + ny + in, ) ;
}
}
if (tu[i][j] == 'N') f.add(i * m + j + out, sink, );
}
}
return f.maxflow(source, sink);
}
int main() {
while() {
string s;
vector<string> tu;
while(getline(cin, s)) {
if (s.length() == ) break;
tu.push_back(s);
}
if (tu.size() == ) break;
printf("%d\n", ans(tu));
}
return ;
}
Tile Cut~网络流入门题的更多相关文章
- poj1273 网络流入门题 dinic算法解决,可作模板使用
Drainage Ditches Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 62078 Accepted: 2384 ...
- POJ-1273Drainage Ditches(网络流入门题,最大流)
Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This ...
- bzoj2049 [Sdoi2008]Cave 洞穴勘测 link cut tree入门
link cut tree入门题 首先说明本人只会写自底向上的数组版(都说了不写指针.不写自顶向下QAQ……) 突然发现link cut tree不难写... 说一下各个函数作用: bool isro ...
- 网络流最经典的入门题 各种网络流算法都能AC。 poj 1273 Drainage Ditches
Drainage Ditches 题目抽象:给你m条边u,v,c. n个定点,源点1,汇点n.求最大流. 最好的入门题,各种算法都可以拿来练习 (1): 一般增广路算法 ford() #in ...
- hdu 1312:Red and Black(DFS搜索,入门题)
Red and Black Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tot ...
- 网络流入门-POJ1459PowerNetwork-Dinic模板
(我有什么错误或者你有什么意见,欢迎留言或私聊!谢谢!) (Ps:以前听说过网络流,想着以后再学,这次中南多校赛也碰到有关网络流的题目,想着这两天试着学学这个吧~~ 这是本人网络流入门第二题,不知道怎 ...
- Cogs 732. [网络流24题] 试题库(二分图)
[网络流24题] 试题库 ★★ 输入文件:testlib.in 输出文件:testlib.out 评测插件 时间限制:1 s 内存限制:128 MB «问题描述: 假设一个试题库中有n道试题.每道试题 ...
- Cogs 739. [网络流24题] 运输问题(费用流)
[网络流24题] 运输问题 ★★ 输入文件:tran.in 输出文件:tran.out 简单对比 时间限制:1 s 内存限制:128 MB «问题描述: «编程任务: 对于给定的m 个仓库和n 个零售 ...
- Cogs 727. [网络流24题] 太空飞行计划(最大权闭合子图)
[网络流24题] 太空飞行计划 ★★☆ 输入文件:shuttle.in 输出文件:shuttle.out 简单对比 时间限制:1 s 内存限制:128 MB [问题描述] W 教授正在为国家航天中心计 ...
随机推荐
- 640. Solve the Equation
class Solution { public: string solveEquation(string equation) { int idx = equation.find('='); , v1 ...
- python2中将Unicode编码的中文和str相互转换
在python2x版本中 关于中文汉字转换 1.中文------字符串格式 >>> s = '汉字' >>> type(s) <type 'str'> ...
- SPOJ SUBLEX
SUBLEX - Lexicographical Substring Search 链接 题意 求第k小的子串.相同的算一个. 分析 建立后缀自动机,在后缀自动机上从一个点经过trans,到另一个点, ...
- 50道基础的java面试题
Java程序员面试题集(1-50) 一.Java基础部分 1.面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: 1)抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象 ...
- Anytime项目开发记录3
应用想要做的好,反馈必然少不了~哈哈~ 用户的反馈.意见.建议,甚至是谩骂,都是对项目的反馈. 如果一个应用没有听取用户的反馈,那么应用会离着用户越来越远.懂得用户要什么是一回事,听得到用户的反馈,则 ...
- 发布npm包 登录报错 E409 Conflict
1.到官网注册个账号,并且验证完邮箱:https://www.npmjs.com/ 2.打开cmd命令行 登录:$npm login 根据提示 一步步完成登录. 3.新建一个项目文件夹: npmtes ...
- Java并发(多线程)
一.多线程的基本概念 1.什么是进程.多进程有什么作用? 大家都使用计算机,当我们打开某一个软件的时候,其实就是启动了一个进程,可以打开任务管理器看看,我们打开的每一个软件,都是一个进程,在同一个操作 ...
- Python request 简单使用
Requests 是用Python语言编写,基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库.它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTT ...
- 6.爬虫 requests库讲解 总结
requests库的总结: 用ProcessOn根据前面的几节内容做了个思维导图:
- Tensorflowonspark安装
1.实验环境 Centos7+Python3.6+Java8+Hadoop2.6+Spark2.3+Tensorflow1.10.0 2.Tensorflow安装 最简单的方式:pip install ...