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 教授正在为国家航天中心计 ...
随机推荐
- (数据科学学习手札19)R中基本统计分析技巧总结
在获取数据,并且完成数据的清洗之后,首要的事就是对整个数据集进行探索性的研究,这个过程中会利用到各种描述性统计量和推断性统计量来初探变量间和变量内部的基本关系,本篇笔者便基于R,对一些常用的数据探索方 ...
- JQuery中的load()、$.get()和$.post()详解 (转)
load() 1.载入HTML文档 load()方法是jQuery中最为简单和常用的Ajax方法,能载入远程HTML代码并插入DOM中. 它的结构为: load(url [,data][,callba ...
- UVA 1175 - Ladies' Choice
1175 - Ladies' Choice 链接 稳定婚姻问题. 代码: #include<bits/stdc++.h> using namespace std; typedef long ...
- P2966 [USACO09DEC]牛收费路径Cow Toll Paths
P2966 [USACO09DEC]牛收费路径Cow Toll Paths 题目描述 Like everyone else, FJ is always thinking up ways to incr ...
- Java 基础------16进制转2进制
我们知道,数字8用二进制表示为:1000 用16进制表示为:8 那么我给你一个16进制的数字,0x7f,他的二进制是什么呢? 一个16进制的位数,用4位表示.比如,0x 7 f 其中: 7用4位二进制 ...
- oracle 开启归档日志模式
摘自:https://www.jianshu.com/p/f8c0e9309ce2 在默认情况下,oracle数据库是在非归日志档模式中创建的,在非归档日志模式中,进行日志切换时会直接重写redo l ...
- ResolutionException: Cannot find candidate artifact for com.google.android.gms:play-services-ads-lite:[10.2.4]
I had the same issue and I think it's solved now. Open AdMobDependencies.cs file, located inside of ...
- Android中通过拨号调起应用的实现方式及特殊情况处理
Android中有时我们会有这样的需求:通过拨号调起我们的程序.这个需求如何实现呢? 思路当然是在我们的应用中实现一个广播接收器(BroadcastReceiver),对打电话时系统发出的广播进行拦截 ...
- 数据结构(python语言)目录链接
第一章 准备工作 课时0:0.数据结构(python语言) 基本概念 算法的代价及度量!!!
- Linux TCP协议使用的变量
Linux /proc/sys/net/ipv4/* 变量 TCP变量:somaxconn - INTEGER listen()的backlog参数的上限,在用户态为SOMAXCONN.默认是1 ...