http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3781
题意:
在n*m矩阵的图定义连通区域为x值或y值相同且颜色相同的连通,连通具有传递性
每次可以把一个连通区域颜色反转(O变X,X变O)
问把所有块的颜色变为X最小的步数
方法:
很巧妙的最短路问题,先建图,然后以每个顶点为起点,找单源最短路的最大的值(也就是最深的深度),然后这个值取min
建图:相邻的块连边权1的边(即:通过1次反转可以使得两个连通块变为一个连通块)
注意:
floyd会TLE,需要邻接表建图
因为是稀疏图且边权为1,所以使用bfs或者spfa或者dijkstra均可
代码:spfa
1 // #pragma comment(linker, "/STACK:102400000,102400000") 2 #include <cstdio> 3 #include <iostream> 4 #include <cstring> 5 #include <string> 6 #include <cmath> 7 #include <set> 8 #include <list> 9 #include <map> 10 #include <iterator> 11 #include <cstdlib> 12 #include <vector> 13 #include <queue> 14 #include <stack> 15 #include <algorithm> 16 #include <functional> 17 using namespace std; 18 typedef long long LL; 19 #define ROUND(x) round(x) 20 #define FLOOR(x) floor(x) 21 #define CEIL(x) ceil(x) 22 const int maxn = 1610; 23 const int maxm = 100010; 24 const int inf = 0x3f3f3f3f; 25 const LL inf64 = 0x3f3f3f3f3f3f3f3fLL; 26 const double INF = 1e30; 27 const double eps = 1e-6; 28 const int P[4] = {0, 0, -1, 1}; 29 const int Q[4] = {1, -1, 0, 0}; 30 const int PP[8] = { -1, -1, -1, 0, 0, 1, 1, 1}; 31 const int QQ[8] = { -1, 0, 1, -1, 1, -1, 0, 1}; 32 char mtx[50][50]; 33 int label[50][50]; 34 int g[maxn][maxn]; 35 struct Edge 36 { 37 int u, v; 38 int w; 39 int next; 40 Edge(int _u = -1, int _v = -1, int _w = -1, int _next = -1): u(_u), v(_v), w(_w), next(_next) {} 41 } edge[maxm]; 42 int n; 43 int N, M; 44 int head[maxn]; 45 int d[maxn]; 46 int en; 47 int ans; 48 void addse(int u, int v, int w) 49 { 50 edge[en] = Edge(u, v, w, head[u]); 51 head[u] = en++; 52 } 53 void adde(int u, int v, int w) 54 { 55 addse(u, v, w); 56 addse(v, u, w); 57 } 58 void init() 59 { 60 memset(g, 0x3f, sizeof(g)); 61 memset(head, -1, sizeof(head)); 62 en = 0; 63 memset(label, -1, sizeof(label)); 64 ans = 0; 65 } 66 void input() 67 { 68 scanf("%d%d", &N, &M); 69 for (int i = 0; i < N; i++) 70 scanf("%s", mtx[i]); 71 } 72 void debug() 73 { 74 // 75 } 76 void dfs(int x, int y, char ch) 77 { 78 label[x][y] = n; 79 for (int i = 0; i < 4; i++) 80 { 81 int nx = x + P[i]; 82 int ny = y + Q[i]; 83 if (nx < 0 || nx >= N || ny < 0 || ny >= M) continue; 84 if (label[nx][ny] == -1 && mtx[nx][ny] == ch) 85 { 86 dfs(nx, ny, ch); 87 } 88 } 89 } 90 void build() 91 { 92 n = 0; 93 for (int i = 0; i < N; i++) 94 { 95 for (int j = 0; j < M; j++) 96 { 97 if (label[i][j] == -1) 98 { 99 dfs(i, j, mtx[i][j]); 100 n++; 101 } 102 } 103 } 104 105 for (int i = 0; i < N; i++) 106 { 107 for (int j = 0; j < M; j++) 108 { 109 for (int p = 0; p < 4; p++) 110 { 111 int nx = i + P[p]; 112 int ny = j + Q[p]; 113 if (nx < 0 || nx >= N || ny < 0 || ny >= M) continue; 114 g[label[i][j]][label[nx][ny]] = g[label[nx][ny]][label[i][j]] = 1; 115 } 116 } 117 } 118 119 for (int i = 0; i < n; i++) 120 { 121 for (int j = i + 1; j < n; j++) 122 { 123 if (g[i][j]==1) 124 { 125 adde(i, j, 1); 126 // cout << j << " "; 127 } 128 } 129 // cout << endl; 130 } 131 } 132 int spfa(int s) 133 { 134 int cnt[maxn]; 135 int mark[maxn]; 136 queue<int> Q; 137 for (int i = 0; i < n; ++i) d[i] = inf; 138 memset(mark, 0, sizeof(mark)); 139 memset(cnt, 0, sizeof(cnt)); 140 d[s] = 0; 141 Q.push(s); 142 mark[s] = 1; 143 cnt[s]++; 144 while (Q.size()) 145 { 146 int u = Q.front(); 147 Q.pop(); 148 mark[u] = 0; 149 for (int i = head[u]; i != -1; i = edge[i].next) 150 { 151 int v = edge[i].v; 152 int w = edge[i].w; 153 if (d[u] + w < d[v]) 154 { 155 d[v] = d[u] + w; 156 if (mark[v] == 0) 157 { 158 mark[v] = 1; 159 Q.push(v); 160 if (++cnt[v] > n) return inf; //有负环,可以用DFS找 161 } 162 } 163 } 164 } 165 int ret = -1; 166 for (int i = 0; i < n; i++) 167 { 168 ret = max(ret, d[i]); 169 } 170 if (ret == -1) return inf; 171 // cout<<"ret:"<<ret<<endl; 172 return ret; 173 } 174 void solve() 175 { 176 build(); 177 178 ans = inf; 179 for (int i = 0; i < n; i++) 180 { 181 ans = min(ans, spfa(i)); 182 } 183 printf("%d\n", ans); 184 } 185 void output() 186 { 187 // 188 } 189 int main() 190 { 191 // std::ios_base::sync_with_stdio(false); 192 #ifndef ONLINE_JUDGE 193 freopen("in.cpp", "r", stdin); 194 #endif 195 196 int T; 197 scanf("%d", &T); 198 while (T--) 199 { 200 init(); 201 input(); 202 solve(); 203 output(); 204 } 205 return 0; 206 }
ZOJ 3781 Paint the Grid Reloaded (最短路),布布扣,bubuko.com
时间: 2024-10-25 15:57:54