首页 > 代码库 > ZOJ 3781 Paint the Grid Reloaded (最短路)

ZOJ 3781 Paint the Grid Reloaded (最短路)

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_JUDGE193     freopen("in.cpp", "r", stdin);194 #endif195 196     int T;197     scanf("%d", &T);198     while (T--)199     {200         init();201         input();202         solve();203         output();204     }205     return 0;206 }
View Code