Gym - 100203I  I WIN

题意:一个n*m的矩阵包含W,I,N三种字符,问相邻的字符最多能组成不重叠的WIN。

思路:比赛的时候没有发现是网络流,,居然一度以为是二分图匹配,,写了一下没过就没改了,,知道了是网络流就好办了。设一个起点一个终点,起点和每个W之间连一条边,N和终点间连一条边,W和I之间连一条边,I和N之间连一条边,不过这里为了避免重复使用同一个I,应改成W到I连一条边,I连一条边到I',再从I'连一条边到N就可以保证最优解了。求一遍最大流即可。

 #include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define LL long long
#define eps 1e-8
#define INF 0x3f3f3f3f
#define MAXN 1005
using namespace std; struct Edge{
int from, to, cap, flow;
//Edge(int u, int v, int c, int f) :from(u), to(v), cap(c), flow(f){};
};
struct Dinic{
int n, m, i, s, t;
Edge e;
vector<Edge> edges;
vector<int> G[MAXN];
int d[MAXN], cur[MAXN];
bool vis[MAXN];
void init(int n){
this->n = n;
for (i = ; i <= n; i++){
G[i].clear();
}
edges.clear();
}
void AddEdge(int from, int to, int cap){
edges.push_back(Edge{ from, to, cap, });
edges.push_back(Edge{ to, from, , });
m = edges.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();
for (i = ; i < G[x].size(); i++){
Edge& e = edges[G[x][i]];
if (!vis[e.to] && e.cap > e.flow){
vis[e.to] = true;
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;
for (int& i = cur[x]; i < G[x].size(); i++){
Edge& e = edges[G[x][i]];
if (d[x] + == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > ){
e.flow += f;
edges[G[x][i] ^ ].flow -= f;
flow += f;
a -= f;
if (a == ) break;
}
}
return flow;
}
int MaxFlow(int s, int t, int need){
int flow = ;
this->s = s;
this->t = t;
while (BFS()){
memset(cur, , sizeof(cur));
flow += DFS(s, INF);
if (flow > need) return flow;
}
return flow;
}
};
char a[][];
Dinic p;
const int step[][] = { , , , , -, , , - };
bool vis[][];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif // OPEN_FILE
int n, m;
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++){
scanf("%s", a[i] + );
}
int s = , t = * n * m + ;
p.init(t);
memset(vis, , sizeof(vis));
for (int i = ; i <= n; i++){
for (int j = ; j <= m; j++){
int u = (i - ) * m + j;
if(a[i][j] == 'W'){
p.AddEdge(s, u, );
for (int k = ; k < ; k++){
int x = i + step[k][];
int y = j + step[k][];
if (x < || y < || x > n || y > m) continue;
if (a[x][y] == 'I'){
p.AddEdge(u, (x - ) * m + y, );
}
}
}
else if (a[i][j] == 'I'){
int v = u + n * m;
p.AddEdge(u, v, );
for (int k = ; k < ; k++){
int x = i + step[k][];
int y = j + step[k][];
if (x < || y < || x > n || y > m) continue;
if (a[x][y] == 'N'){
p.AddEdge(v, (x - ) * m + y, );
if (vis[x][y]) continue;
p.AddEdge((x - ) * m + y, t, );
vis[x][y] = true;
}
}
}
}
}
int ans = p.MaxFlow(s, t, INF);
printf("%d\n", ans);
}

最新文章

  1. Asp.net Core准备工作
  2. iOS 自定义的对象类型的解档和归档
  3. 微信 6.5.1 for iOS发布 可以在朋友圈分享相册中的视频
  4. 使用 Java 开发兼容 IPv6 的网络应用程序
  5. 基本的编程原则SOLID
  6. html学习笔记二
  7. memcache command
  8. cc2530启动流程---广播发送数据
  9. Chapter5 – 碰撞检测
  10. 一个SQL存储过程面试题(比较简单)
  11. 实际项目开发需要注意的tips
  12. openstack Ocata版本 python
  13. Nearest Common Ancestors (POJ 1330)
  14. vue实现双向绑定的简单原理: defineProperty
  15. 【总结】 Lucas定理
  16. ArcGIS 关于Web_Mercator
  17. express-partials使用方法
  18. mysql通过“延迟关联”进行limit分页查询优化的一个实例
  19. scala 学习笔记十二 继承
  20. CF 1064 D. Labyrinth

热门文章

  1. YUM安装MONGODB发生Error in PREIN scriptlet in rpm package mongodb-enterprise-server-4.0.2-1.el6.x86_64错误
  2. 紫书 例题 11-1 UVa 12219 (表达式树)
  3. ActiveMQ学习总结(9)——Linux中安装ActiveMQ
  4. oracle新手随记10
  5. [CQOI2009] 叶子的颜色 解题报告(树形DP)
  6. 使用sshfs来挂载远程的文件
  7. Kali linux 2016.2(Rolling)里Metasploit的常用模块
  8. VS导出方法名和方法备注的方法
  9. 泪奔,配好了bioconductor环境
  10. TabLayout中Indicator的样式修改