您的位置:首页 > 理论基础 > 计算机网络

Gym - 100203I I WIN 网络流

2015-08-16 00:27 399 查看
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 = 0; i <= n; i++){
G[i].clear();
}
edges.clear();
}
void AddEdge(int from, int to, int cap){
edges.push_back(Edge{ from, to, cap, 0 });
edges.push_back(Edge{ to, from, 0, 0 });
m = edges.size();
G[from].push_back(m - 2);
G[to].push_back(m - 1);
}
bool BFS(){
memset(vis, 0, sizeof(vis));
queue<int> Q;
Q.push(s);
d[s] = 0;
vis[s] = 1;
while (!Q.empty()){
int x = Q.front();
Q.pop();
for (i = 0; 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] + 1;
Q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int x, int a){
if (x == t || a == 0) return a;
int flow = 0, f;
for (int& i = cur[x]; i < G[x].size(); i++){
Edge& e = edges[G[x][i]];
if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0){
e.flow += f;
edges[G[x][i] ^ 1].flow -= f;
flow += f;
a -= f;
if (a == 0) break;
}
}
return flow;
}
int MaxFlow(int s, int t, int need){
int flow = 0;
this->s = s;
this->t = t;
while (BFS()){
memset(cur, 0, sizeof(cur));
flow += DFS(s, INF);
if (flow > need) return flow;
}
return flow;
}
};
char a[50][50];
Dinic p;
const int step[4][2] = { 1, 0, 0, 1, -1, 0, 0, -1 };
bool vis[25][25];
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 = 1; i <= n; i++){
scanf("%s", a[i] + 1);
}
int s = 0, t = 2 * n * m + 1;
p.init(t);
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m; j++){
int u = (i - 1) * m + j;
if(a[i][j] == 'W'){
p.AddEdge(s, u, 1);
for (int k = 0; k < 4; k++){
int x = i + step[k][0];
int y = j + step[k][1];
if (x < 1 || y < 1 || x > n || y > m) continue;
if (a[x][y] == 'I'){
p.AddEdge(u, (x - 1) * m + y, 1);
}
}
}
else if (a[i][j] == 'I'){
int v = u + n * m;
p.AddEdge(u, v, 1);
for (int k = 0; k < 4; k++){
int x = i + step[k][0];
int y = j + step[k][1];
if (x < 1 || y < 1 || x > n || y > m) continue;
if (a[x][y] == 'N'){
p.AddEdge(v, (x - 1) * m + y, 1);
if (vis[x][y]) continue;
p.AddEdge((x - 1) * m + y, t, 1);
vis[x][y] = true;
}
}
}
}
}
int ans = p.MaxFlow(s, t, INF);
printf("%d\n", ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: