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 ", 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 }
dijkstra:需要用优先队列优化dijkstra
1 /* 2 *floyd TLE 3 */ 4 // #pragma comment(linker, "/STACK:102400000,102400000") 5 #include <cstdio> 6 #include <iostream> 7 #include <cstring> 8 #include <string> 9 #include <cmath> 10 #include <set> 11 #include <list> 12 #include <map> 13 #include <iterator> 14 #include <cstdlib> 15 #include <vector> 16 #include <queue> 17 #include <stack> 18 #include <algorithm> 19 #include <functional> 20 using namespace std; 21 typedef long long LL; 22 #define ROUND(x) round(x) 23 #define FLOOR(x) floor(x) 24 #define CEIL(x) ceil(x) 25 const int maxn = 1610; 26 const int maxm = 100010; 27 const int inf = 0x3f3f3f3f; 28 const LL inf64 = 0x3f3f3f3f3f3f3f3fLL; 29 const double INF = 1e30; 30 const double eps = 1e-6; 31 const int P[4] = {0, 0, -1, 1}; 32 const int Q[4] = {1, -1, 0, 0}; 33 const int PP[8] = { -1, -1, -1, 0, 0, 1, 1, 1}; 34 const int QQ[8] = { -1, 0, 1, -1, 1, -1, 0, 1}; 35 char mtx[50][50]; 36 int label[50][50]; 37 int g[maxn][maxn]; 38 struct Edge 39 { 40 int u, v; 41 int w; 42 int next; 43 Edge(int _u = -1, int _v = -1, int _w = -1, int _next = -1): u(_u), v(_v), w(_w), next(_next) {} 44 } edge[maxm]; 45 int n; 46 int N, M; 47 int head[maxn]; 48 int d[maxn]; 49 int en; 50 int ans; 51 void addse(int u, int v, int w) 52 { 53 edge[en] = Edge(u, v, w, head[u]); 54 head[u] = en++; 55 } 56 void adde(int u, int v, int w) 57 { 58 addse(u, v, w); 59 addse(v, u, w); 60 } 61 void init() 62 { 63 memset(g, 0x3f, sizeof(g)); 64 memset(head, -1, sizeof(head)); 65 en = 0; 66 memset(label, -1, sizeof(label)); 67 ans = 0; 68 } 69 void input() 70 { 71 scanf("%d%d", &N, &M); 72 for (int i = 0; i < N; i++) 73 scanf("%s", mtx[i]); 74 } 75 void debug() 76 { 77 // 78 } 79 void dfs(int x, int y, char ch) 80 { 81 label[x][y] = n; 82 for (int i = 0; i < 4; i++) 83 { 84 int nx = x + P[i]; 85 int ny = y + Q[i]; 86 if (nx < 0 || nx >= N || ny < 0 || ny >= M) continue; 87 if (label[nx][ny] == -1 && mtx[nx][ny] == ch) 88 { 89 dfs(nx, ny, ch); 90 } 91 } 92 } 93 void build() 94 { 95 n = 0; 96 for (int i = 0; i < N; i++) 97 { 98 for (int j = 0; j < M; j++) 99 { 100 if (label[i][j] == -1) 101 { 102 dfs(i, j, mtx[i][j]); 103 n++; 104 } 105 } 106 } 107 108 for (int i = 0; i < N; i++) 109 { 110 for (int j = 0; j < M; j++) 111 { 112 for (int p = 0; p < 4; p++) 113 { 114 int nx = i + P[p]; 115 int ny = j + Q[p]; 116 if (nx < 0 || nx >= N || ny < 0 || ny >= M) continue; 117 g[label[i][j]][label[nx][ny]] = g[label[nx][ny]][label[i][j]] = 1; 118 } 119 } 120 } 121 122 for (int i = 0; i < n; i++) 123 { 124 for (int j = i + 1; j < n; j++) 125 { 126 if (g[i][j] == 1) 127 { 128 adde(i, j, 1); 129 // cout << j << " "; 130 } 131 } 132 // cout << endl; 133 } 134 } 135 int Dist[maxn]; 136 struct State 137 { 138 int p, c; //p: 点 c: 值 139 State(int _p, int _c): p(_p), c(_c) {} 140 bool operator<(const State &o)const 141 { 142 return c > o.c; 143 } 144 }; 145 int Dijstra(int st) 146 { 147 priority_queue<State> Q; 148 fill(Dist, Dist + n, inf); 149 Dist[st] = 0; 150 Q.push(State(st, 0)); 151 while (!Q.empty()) 152 { 153 State t = Q.top(); 154 Q.pop(); 155 if (t.c > Dist[t.p])continue; 156 int ncost; 157 for (int i = head[t.p]; i != -1; i = edge[i].next) 158 if ((ncost = t.c + edge[i].w) < Dist[edge[i].v]) 159 { 160 Dist[edge[i].v] = ncost; 161 Q.push(State(edge[i].v, Dist[edge[i].v])); 162 } 163 } 164 int ret = -1; 165 for (int i = 0; i < n; i++) 166 ret = max(ret, Dist[i]); 167 if (ret == -1) return inf; 168 return ret; 169 } 170 void solve() 171 { 172 build(); 173 174 ans = inf; 175 for (int i = 0; i < n; i++) 176 { 177 ans = min(ans, Dijstra(i)); 178 } 179 printf("%d ", ans); 180 } 181 void output() 182 { 183 // 184 } 185 int main() 186 { 187 // std::ios_base::sync_with_stdio(false); 188 #ifndef ONLINE_JUDGE 189 freopen("in.cpp", "r", stdin); 190 #endif 191 192 int T; 193 scanf("%d", &T); 194 while (T--) 195 { 196 init(); 197 input(); 198 solve(); 199 output(); 200 } 201 return 0; 202 }