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_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 }
View Code

 

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\n", 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 }
View Code

 

posted @ 2014-07-29 19:28  xysmlx  阅读(355)  评论(2编辑  收藏  举报