原题链接:http://codeforces.com/gym/100203/attachments/download/1702/statements.pdf

题解

首先寻找每个I,然后枚举形状,如果匹配的话,就将源点连一条边到当前匹配的W,再从W连条边到I,I需要拆点,然后将拆点后面的那个点连接到N,从N连接到汇点。所有边的容量都是1。需要注意避免产生重边。然后最大流就是答案。

代码

#include<iostream>
#include<stack>
#include<vector>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#define MAX_V 1500
#define MAX_N 10004
#define INF 2500005
using namespace std; struct edge{int to,cap,rev;bool isRev;}; vector<edge> G[MAX_N];
int level[MAX_V];
int iter[MAX_V]; void add_edge(int from,int to,int cap) {
G[from].push_back((edge) {to, cap, G[to].size(),});
G[to].push_back((edge) {from, , G[from].size() - ,});
} void bfs(int s) {
memset(level, -, sizeof(level));
queue<int> que;
level[s] = ;
que.push(s);
while (!que.empty()) {
int v = que.front();
que.pop();
for (int i = ; i < G[v].size(); i++) {
edge &e = G[v][i];
if (e.cap > && level[e.to] < ) {
level[e.to] = level[v] + ;
que.push(e.to);
}
}
}
} int dfs(int v,int t,int f) {
if (v == t)return f;
for (int &i = iter[v]; i < G[v].size(); i++) {
edge &e = G[v][i];
if (e.cap > && level[v] < level[e.to]) {
int d = dfs(e.to, t, min(f, e.cap));
if (d > ) {
e.cap -= d;
G[e.to][e.rev].cap += d;
return d;
}
}
}
return ;
} int max_flow(int s,int t) {
int flow = ;
for (; ;) {
bfs(s);
if (level[t] < )return flow;
memset(iter, , sizeof(iter));
int f;
while ((f = dfs(s, t, INF)) > ) {
flow += f;
}
}
} string ss[];
int n,m;
//int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0}; int Hash(int x,int y) {
return x * m + y;
} int S=;
int T=; bool vis[MAX_V]; void AddEdges(int W,int I,int N) {
if (!vis[W])
add_edge(S, W, );
add_edge(W, I, );
add_edge(I + n * m + , N, );
if (!vis[N])
add_edge(N, T, );
vis[W] = vis[N] = ;
} int main() {
cin.sync_with_stdio(false);
cin >> n >> m;
for (int i = ; i < n; i++)
cin >> ss[i];
for (int i = ; i < n; i++)
for (int j = ; j < m; j++) {
if (ss[i][j] != 'I')continue;
add_edge(Hash(i, j), Hash(i, j) + n * m+, );
int u, v;
u = j - ;
v = j + ;
if (u >= && v < m) {
if (ss[i][u] == 'N' && ss[i][v] == 'W')swap(u, v);
if (ss[i][u] == 'W' && ss[i][v] == 'N')
AddEdges(Hash(i, u), Hash(i, j), Hash(i, v));
}
u = i - ;
v = i + ;
if (u >= && v < n) {
if (ss[u][j] == 'N' && ss[v][j] == 'W')swap(u, v);
if (ss[u][j] == 'W' && ss[v][j] == 'N')
AddEdges(Hash(u, j), Hash(i, j), Hash(v, j));
}
u = j - ;
v = i - ;
if (u >= && v >= ) {
if (ss[i][u] == 'N' && ss[v][j] == 'W')
AddEdges(Hash(v, j), Hash(i, j), Hash(i, u));
if (ss[i][u] == 'W' && ss[v][j] == 'N')
AddEdges(Hash(i, u), Hash(i, j), Hash(v, j));
}
u = i - ;
v = j + ;
if (u >= && v < m) {
if (ss[u][j] == 'N' && ss[i][v] == 'W')
AddEdges(Hash(i, v), Hash(i, j), Hash(u, j));
if (ss[u][j] == 'W' && ss[i][v] == 'N')
AddEdges(Hash(u, j), Hash(i, j), Hash(i, v));
}
u = j + ;
v = i + ;
if (u < m && v < n) {
if (ss[i][u] == 'N' && ss[v][j] == 'W')
AddEdges(Hash(v, j), Hash(i, j), Hash(i, u));
if (ss[i][u] == 'W' && ss[v][j] == 'N')
AddEdges(Hash(i, u), Hash(i, j), Hash(v, j));
}
u = i + ;
v = j - ;
if (u < n && v >= ) {
if (ss[u][j] == 'N' && ss[i][v] == 'W')
AddEdges(Hash(i, v), Hash(i, j), Hash(u, j));
if (ss[u][j] == 'W' && ss[i][v] == 'N')
AddEdges(Hash(u, j), Hash(i, j), Hash(i, v));
}
}
int f = max_flow(S, T);
cout << f << endl;
return ;
}

Codeforces Gym 100203I I WIN 最大流的更多相关文章

  1. Gym - 100203I I WIN 网络流

    Gym - 100203I  I WIN 题意:一个n*m的矩阵包含W,I,N三种字符,问相邻的字符最多能组成不重叠的WIN. 思路:比赛的时候没有发现是网络流,,居然一度以为是二分图匹配,,写了一下 ...

  2. Codeforces Gym 101190M Mole Tunnels - 费用流

    题目传送门 传送门 题目大意 $m$只鼹鼠有$n$个巢穴,$n - 1$条长度为$1$的通道将它们连通且第$i(i > 1)$个巢穴与第$\left\lfloor \frac{i}{2}\rig ...

  3. Codeforces Gym 100203I I - I WIN 网络流最大流

    I - I WINTime Limit: 2 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view.acti ...

  4. codeforce Gym 100203I I WIN (网络流)

    把'I'拆成容量为1一条边,一个入点一个出点,入点和相邻的'W'连一条容量为1的边,出点和相邻的'N'连一条容量为1,所有的'W'和源点连一条容量为1边,所有的'N'和汇点连一条容量为1的边,表示只能 ...

  5. Codeforces Gym 101252D&&floyd判圈算法学习笔记

    一句话题意:x0=1,xi+1=(Axi+xi%B)%C,如果x序列中存在最早的两个相同的元素,输出第二次出现的位置,若在2e7内无解则输出-1. 题解:都不到100天就AFO了才来学这floyd判圈 ...

  6. Codeforces Gym 101623A - 动态规划

    题目传送门 传送门 题目大意 给定一个长度为$n$的序列,要求划分成最少的段数,然后将这些段排序使得新序列单调不减. 考虑将相邻的相等的数缩成一个数. 假设没有分成了$n$段,考虑最少能够减少多少划分 ...

  7. 【Codeforces Gym 100725K】Key Insertion

    Codeforces Gym 100725K 题意:给定一个初始全0的序列,然后给\(n\)个查询,每一次调用\(Insert(L_i,i)\),其中\(Insert(L,K)\)表示在第L位插入K, ...

  8. Codeforces gym 101343 J.Husam and the Broken Present 2【状压dp】

     2017 JUST Programming Contest 2.0 题目链接:Codeforces gym 101343 J.Husam and the Broken Present 2 J. Hu ...

  9. codeforces gym 100553I

    codeforces gym 100553I solution 令a[i]表示位置i的船的编号 研究可以发现,应是从中间开始,往两边跳.... 于是就是一个点往两边的最长下降子序列之和减一 魔改树状数 ...

随机推荐

  1. python列表中的深浅copy

    列表中的赋值和平常的赋值是不一样的,看下面的代码: In [1]: a = 1 In [2]: b = a In [3]: a Out[3]: 1 In [4]: b Out[4]: 1 In [5] ...

  2. 【草稿】JS中如何操作时间

    如何声明时间变量 如何设置时间变量的时.分.秒.毫秒 如何根据字符串变量,声明指定的时间变量 如何比较两个时间变量 代码如下: $(function () { var d = new Date(); ...

  3. 在spring boot中使用webSocket组件(一)

    最近在项目中使用到了spring的webSocket组件,在这里和大家分享下,如有错误,欢迎大家指正. 在这里我使用的IDE工具是Intellij idea,框架是spring boot.spring ...

  4. WPF使用异步+绑定的方式处理大数据量

    WPF的优势在于界面处理,即使是这样,在面对大数据量的时候也免不了界面假死,同一个线程里处理界面跟大数据量,这是不可避免的.解决办法还是有的,可以使用分页加载,虚拟加载,动态加载,增加条件限制... ...

  5. 探究灰度测试(A/B Testing)

    一段小插曲 前段时间产品改版,产品经理为了改进用户体验,就决定改版用户的注册流程页面,但又怕身份证注册验证接口不稳定(第三方的身份证校验). 于是产品经理就让我通过随机概率去控制注册流程,让一部分用户 ...

  6. Android 程序 LinearLayout布局 参数layout_weight 探讨

    官方参考文档 对LinearLayout.LayoutParams中的android:layout_weight解释如下:Indicates how much of the extra space i ...

  7. [整理]配置SSH密钥自动登录远程服务器

    原理: 公钥私钥匹配通过验证,允许访问服务器. 简单步骤: 1.在本地创建一对密钥 2.将公钥传到需要访问的服务器上 3.将公钥放入服务器的authorized_keys,确保访问时能通过验证 4.本 ...

  8. 区别Transform、Transition、Animation

    另一篇参考文章:http://www.7755.me/Article/CSS3/39/ 近来上班之外就是研究研究CSS动画,下面是第一阶段总结.话说为加强记忆,实则想抛砖引玉!   标题直译一下就是: ...

  9. ora-08104 该索引对象 159639 正在被联机建立或重建

    SSH远程连接数据库创建索引,网络中断后,删除索引信息报ora-08104 解决方法: 使用ONLINE_INDEX_CLEAN清除索引痕迹 在sys用户下执行 SQL> conn /as sy ...

  10. 设计模式(五)原型模式 Prototype

    原型模式: 原型模式,是指基于一个已经给定的对象,通过拷贝的方式,创建一个新的对象,这个给定对象,就是“原型”. 在 Java 中,原型模式体现为 Object 的 clone() 方法. 所有类都可 ...