Codeforces Gym 100203I I WIN 最大流
原题链接: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 最大流的更多相关文章
- Gym - 100203I I WIN 网络流
Gym - 100203I I WIN 题意:一个n*m的矩阵包含W,I,N三种字符,问相邻的字符最多能组成不重叠的WIN. 思路:比赛的时候没有发现是网络流,,居然一度以为是二分图匹配,,写了一下 ...
- Codeforces Gym 101190M Mole Tunnels - 费用流
题目传送门 传送门 题目大意 $m$只鼹鼠有$n$个巢穴,$n - 1$条长度为$1$的通道将它们连通且第$i(i > 1)$个巢穴与第$\left\lfloor \frac{i}{2}\rig ...
- 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 ...
- codeforce Gym 100203I I WIN (网络流)
把'I'拆成容量为1一条边,一个入点一个出点,入点和相邻的'W'连一条容量为1的边,出点和相邻的'N'连一条容量为1,所有的'W'和源点连一条容量为1边,所有的'N'和汇点连一条容量为1的边,表示只能 ...
- Codeforces Gym 101252D&&floyd判圈算法学习笔记
一句话题意:x0=1,xi+1=(Axi+xi%B)%C,如果x序列中存在最早的两个相同的元素,输出第二次出现的位置,若在2e7内无解则输出-1. 题解:都不到100天就AFO了才来学这floyd判圈 ...
- Codeforces Gym 101623A - 动态规划
题目传送门 传送门 题目大意 给定一个长度为$n$的序列,要求划分成最少的段数,然后将这些段排序使得新序列单调不减. 考虑将相邻的相等的数缩成一个数. 假设没有分成了$n$段,考虑最少能够减少多少划分 ...
- 【Codeforces Gym 100725K】Key Insertion
Codeforces Gym 100725K 题意:给定一个初始全0的序列,然后给\(n\)个查询,每一次调用\(Insert(L_i,i)\),其中\(Insert(L,K)\)表示在第L位插入K, ...
- 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 ...
- codeforces gym 100553I
codeforces gym 100553I solution 令a[i]表示位置i的船的编号 研究可以发现,应是从中间开始,往两边跳.... 于是就是一个点往两边的最长下降子序列之和减一 魔改树状数 ...
随机推荐
- win10安装pytorch——前面有坑,快跳进去鸭
嗯!花费了不少时间才把pytorch安装成功.主要原因就是: 清华和中科大的Anaconda国内镜像源关闭了 activate.bat 不是内部或外部命令(这个真实奇怪) 1. 安装过程 可以去Ana ...
- python之自定义排序函数sorted()
sorted()也是一个高阶函数,它可以接收一个比较函数来实现自定义排序,比较函数的定义是,传入两个待比较的元素 x, y,如果 x 应该排在 y 的前面,返回 -1,如果 x 应该排在 y 的后面, ...
- makedown语法
文章转载至:https://blog.csdn.net/u014061630/article/details/81359144#1-%E5%BF%AB%E6%8D%B7%E9%94%AE 前言 写过博 ...
- socketserver源码剖析
作者:人世间链接:https://www.jianshu.com/p/357e436936bf來源:简书简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处 BaseServer 和 B ...
- Mysql - 安装及初始化设置
1. 下载mysql-5.7.13-tar.gz http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.13-linux-glibc2.5-x8 ...
- Leetcode 421.数组中两数的最大异或值
数组中两数的最大异或值 给定一个非空数组,数组中元素为 a0, a1, a2, … , an-1,其中 0 ≤ ai < 231 . 找到 ai 和aj 最大的异或 (XOR) 运算结果,其中0 ...
- [python IO学习篇] [打开包含中文路径的文件]
https://my.oschina.net/mcyang000/blog/289460 打开路径含有中文的文件时,要注意: 1 在windows对文件名编码是采用gbk等进行编码保存,所以要将文 ...
- 2.启动ABP ASP.NET ZERO
1.使用VS2017打开项目,等待自动还原程序包结束 2.生成项目,确保项目全部生成成功 3.生成数据库 (1).将项目“MyCompanyName.AbpZeroTemplate.EntityFra ...
- 九度oj 题目1084:整数拆分 清华大学2010年机试题目
题目描述: 一个整数总可以拆分为2的幂的和,例如:7=1+2+4 7=1+2+2+2 7=1+1+1+4 7=1+1+1+2+2 7=1+1+1+1+1+2 7=1+1+1+1+1+1+1总共有六种不 ...
- PHP_命名空间
namespace NS; define(__NAMESPACE__ .'\foo','111'); define('foo','222'); echo foo; // 111. echo \foo; ...