码迷,mamicode.com
首页 > Windows程序 > 详细

Gym - 100203I I WIN 网络流

时间:2015-08-16 02:01:42      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:

 Gym - 100203I  I WIN

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

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

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <fstream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <deque>
  7 #include <vector>
  8 #include <queue>
  9 #include <string>
 10 #include <cstring>
 11 #include <map>
 12 #include <stack>
 13 #include <set>
 14 #define LL long long
 15 #define eps 1e-8
 16 #define INF 0x3f3f3f3f
 17 #define MAXN 1005
 18 using namespace std;
 19 
 20 struct Edge{
 21     int from, to, cap, flow;
 22     //Edge(int u, int v, int c, int f) :from(u), to(v), cap(c), flow(f){};
 23 };
 24 struct Dinic{
 25     int n, m, i, s, t;
 26     Edge e;
 27     vector<Edge> edges;
 28     vector<int> G[MAXN];
 29     int d[MAXN], cur[MAXN];
 30     bool vis[MAXN];
 31     void init(int n){
 32         this->n = n;
 33         for (i = 0; i <= n; i++){
 34             G[i].clear();
 35         }
 36         edges.clear();
 37     }
 38     void AddEdge(int from, int to, int cap){
 39         edges.push_back(Edge{ from, to, cap, 0 });
 40         edges.push_back(Edge{ to, from, 0, 0 });
 41         m = edges.size();
 42         G[from].push_back(m - 2);
 43         G[to].push_back(m - 1);
 44     }
 45     bool BFS(){
 46         memset(vis, 0, sizeof(vis));
 47         queue<int> Q;
 48         Q.push(s);
 49         d[s] = 0;
 50         vis[s] = 1;
 51         while (!Q.empty()){
 52             int x = Q.front();
 53             Q.pop();
 54             for (i = 0; i < G[x].size(); i++){
 55                 Edge& e = edges[G[x][i]];
 56                 if (!vis[e.to] && e.cap > e.flow){
 57                     vis[e.to] = true;
 58                     d[e.to] = d[x] + 1;
 59                     Q.push(e.to);
 60                 }
 61             }
 62         }
 63         return vis[t];
 64     }
 65     int DFS(int x, int a){
 66         if (x == t || a == 0) return a;
 67         int flow = 0, f;
 68         for (int& i = cur[x]; i < G[x].size(); i++){
 69             Edge& e = edges[G[x][i]];
 70             if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0){
 71                 e.flow += f;
 72                 edges[G[x][i] ^ 1].flow -= f;
 73                 flow += f;
 74                 a -= f;
 75                 if (a == 0) break;
 76             }
 77         }
 78         return flow;
 79     }
 80     int MaxFlow(int s, int t, int need){
 81         int flow = 0;
 82         this->s = s;
 83         this->t = t;
 84         while (BFS()){
 85             memset(cur, 0, sizeof(cur));
 86             flow += DFS(s, INF);
 87             if (flow > need) return flow;
 88         }
 89         return flow;
 90     }
 91 };
 92 char a[50][50];
 93 Dinic p;
 94 const int step[4][2] = { 1, 0, 0, 1, -1, 0, 0, -1 };
 95 bool vis[25][25];
 96 int main()
 97 {
 98 #ifndef ONLINE_JUDGE
 99     freopen("in.txt", "r", stdin);
100     //freopen("out.txt", "w", stdout);
101 #endif // OPEN_FILE
102     int n, m;
103     scanf("%d%d", &n, &m);
104     for (int i = 1; i <= n; i++){
105         scanf("%s", a[i] + 1);
106     }
107     int s = 0, t = 2 * n * m + 1;
108     p.init(t);
109     memset(vis, 0, sizeof(vis));
110     for (int i = 1; i <= n; i++){
111         for (int j = 1; j <= m; j++){
112             int u = (i - 1) * m + j;
113             if(a[i][j] == W){
114                 p.AddEdge(s, u, 1);
115                 for (int k = 0; k < 4; k++){
116                     int x = i + step[k][0];
117                     int y = j + step[k][1];
118                     if (x < 1 || y < 1 || x > n || y > m) continue;
119                     if (a[x][y] == I){
120                         p.AddEdge(u, (x - 1) * m + y, 1);
121                     }
122                 }
123             }
124             else if (a[i][j] == I){
125                 int v = u + n * m;
126                 p.AddEdge(u, v, 1);
127                 for (int k = 0; k < 4; k++){
128                     int x = i + step[k][0];
129                     int y = j + step[k][1];
130                     if (x < 1 || y < 1 || x > n || y > m) continue;
131                     if (a[x][y] == N){
132                         p.AddEdge(v, (x - 1) * m + y, 1);
133                         if (vis[x][y]) continue;
134                         p.AddEdge((x - 1) * m + y, t, 1);
135                         vis[x][y] = true;
136                     }
137                 }
138             }
139         }
140     }
141     int ans = p.MaxFlow(s, t, INF);
142     printf("%d\n", ans);
143 }

 

Gym - 100203I I WIN 网络流

标签:

原文地址:http://www.cnblogs.com/macinchang/p/4733443.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!