原题链接: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. Linux异常处理体系结构

    arm11处理器裸机的异常与中断处理参考: [OK6410裸机程序]异常处理 [OK6410裸机程序]按键中断 另外参考一篇:Linux中断体系结构 在ARM V4及V4T以后的大部分处理器中,中断向 ...

  2. poj 2251 三维地图最短路径问题 bfs算法

    题意:给你一个三维地图,然后让你走出去,找到最短路径. 思路:bfs 每个坐标的表示为 x,y,z并且每个点都需要加上时间 t struct node{ int x, y, z; int t;}; b ...

  3. activity-alias

    activity-alias标签,它有一个属性叫android:targetActivity,这个属性就是用来为该标签设置目标Activity的,或者说它就是这个目标Activity的别名.至此我们已 ...

  4. [转载]ExtJs4 笔记(2) ExtJs对js基本语法扩展支持

    作者:李盼(Lipan)出处:[Lipan] (http://www.cnblogs.com/lipan/) 本篇主要介绍一下ExtJs对JS基本语法的扩展支持,包括动态加载.类的封装等. 一.动态引 ...

  5. jmeter所有版本下载路径

    https://archive.apache.org/dist/jmeter/binaries/

  6. cobbler 安装centos7.3时GPT问题(五)

    磁盘分区表MBR和GPT介绍: MBR(Master Boot Record):最大只支持2 TB的盘,最多只支持4个主分区,信息只存储在一个区域. GPT(GUID partition table) ...

  7. Xcode中断点的使用

    注:本文由破船译自:albertopasca.本文由HoNooD在iosfeed站点上做了推荐. 这里先推荐两篇Xcode相关的文章: Xcode Code Snippets iOS调试 — 基本技巧 ...

  8. iOS开发笔记--UILabel的相关属性设置

    在iOS编程中UILabel是一个常用的控件,下面分享一下UILabel的相关属性设置的方法. 很多学习iOS6编程都是从storyboard开始,用到UILabel时是将控件拖到storyboard ...

  9. Welcome-to-Swift-09类和结构体(Classes and Structures)

    类和结构体是人们构建代码所用的一种通用且灵活的构造体.为了在类和结构体中实现各种功能,我们必须要严格按照对于常量,变量以及函数所规定的语法规则来定义属性和添加方法. 与其他编程语言所不同的是,Swif ...

  10. 【Luogu】P3746组合数问题(矩阵)

    题目链接 哇我一个活人的智商被题目碾压了 可以把问题转化为有nk个物品,问拿i件物品的方案数有多少种,其中i%k=r. 然后矩阵乘法加速DP即可. #include<cstdio> #in ...