题意:一个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 ", ans); 143 }