码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5740 - Glorious Brilliance

时间:2016-07-31 01:45:25      阅读:446      评论:0      收藏:0      [点我收藏+]

标签:

题意:

    给出已0 1染色的无向图(不一定联通),一次操作为一对相邻点颜色互换.  

    问使任意相邻点颜色不同,最少需要多少次操作

分析:

    交换两点的代价即为两点间最短路.

    故用BFS找出所有点到任意点的最短距离,并记录路径.
   

    对于每个连通块,按照相邻点颜色不同重新染色一遍,若发现已给的01数目与染色需要01数目不符,则不可能   

    不然 ,则根据已给的01数目与染色需要01数目,确定匹配的点集.
   

    最后KM算法算出最小权值匹配即可   

    确定匹配后,分析下同一路上的交换顺序,确定交换步骤

 

    不算难,就是麻烦

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <queue>
  5 #include <vector>
  6 using namespace std;
  7 const int INF=0x3f3f3f3f;
  8 const int MAXN=505;
  9 const int MAXM = 505*505;
 10 
 11 int map[MAXN][MAXN];//二分图描述 
 12 int linker[MAXN],lx[MAXN],ly[MAXN];
 13 int slack[MAXN];
 14 int nx,ny;
 15 bool visx[MAXN],visy[MAXN];
 16 
 17 bool DFS(int x)
 18 {
 19     int y;
 20     visx[x] = 1;
 21     for(y = 0;y < ny; ++y)
 22     {
 23         if(visy[y]) continue;
 24         int tmp = lx[x] + ly[y] - map[x][y];
 25         if(tmp == 0)
 26         {
 27             visy[y] = 1;
 28             if(linker[y] == -1 || DFS(linker[y]))
 29             {
 30                 linker[y] = x;
 31                 return 1;
 32             }
 33         }
 34         else if(slack[y] > tmp)
 35             slack[y] = tmp;
 36     } 
 37     return 0;
 38 }
 39 int KM()
 40 {
 41     for(int i = 0;i < nx; ++i) linker[i] = -1,ly[i] = 0;
 42     for(int i = 0;i < nx; ++i)
 43     {
 44         lx[i] = -INF;
 45         for(int j = 0;j < ny; ++j)
 46             if(map[i][j] > lx[i]) 
 47                 lx[i] = map[i][j];
 48     }
 49     for(int x = 0;x < nx; ++x)
 50     {
 51         for(int i = 0;i < ny; ++i) slack[i] = INF;
 52         while(1)
 53         {
 54             for(int i = 0;i < nx; ++i) visx[i] = 0;
 55             for(int i = 0;i < ny; ++i) visy[i] = 0;
 56             if(DFS(x)) break;
 57             int d = INF;
 58             for(int i = 0;i < ny; ++i)
 59                 if(!visy[i] && d > slack[i])
 60                     d = slack[i];
 61             for(int i = 0;i < nx; ++i)
 62                 if(visx[i])
 63                     lx[i] -= d;
 64             for(int i = 0;i < ny; ++i)
 65                 if(visy[i]) ly[i] += d;
 66                 else slack[i] -= d;
 67         }
 68     }
 69     int res = 0;
 70     for(int i = 0;i < ny;++i)
 71         if(linker[i] != -1)
 72             res += map[ linker[i] ][i];
 73     return res;
 74 }
 75 
 76 int g[MAXN][MAXN],col[MAXN];
 77 vector<int> X,Y,Left,Right;//X 1 Y 0 
 78 char s[MAXN];
 79 int n,m,ans;
 80 queue<int> p;
 81 vector<int> G[MAXN];
 82 
 83 bool BFS(int x,int c)//染色 
 84 {
 85     while(!p.empty()) p.pop();
 86     col[x] = c;
 87     if(c) X.push_back(x);
 88     else Y.push_back(x);
 89     p.push(x);
 90     int size,i;
 91     while(!p.empty())
 92     {
 93         x = p.front(); p.pop();
 94         size = G[x].size();
 95         for(i = 0; i < size; ++i)
 96         {
 97             if(col[ G[x][i] ] == col[x] ) return 0;
 98             else if(col[ G[x][i] ] == -1)
 99             {
100                 col[ G[x][i] ] = col[x]^1;
101                 if( col[ G[x][i] ] ) X.push_back( G[x][i] );//1 
102                 else Y.push_back( G[x][i] );//0 
103                 p.push( G[x][i] );
104             }
105         }
106     }
107     return 1;
108 }
109 vector<int> path[MAXN][MAXN];
110 int vis[MAXN],Pair1[MAXN],Pair2[MAXN],*Pair;
111 pair<int,int> Ans[MAXM];//答案 
112 
113 void GetPath(int u)//找到最短路并记录路径 
114 {
115     int i, t, v;
116     for(i = 0; i <= n; ++i) vis[i] = 0; 
117     while(!p.empty()) p.pop();
118     p.push(u); 
119     path[u][u].push_back(u);
120     vis[u] = 1;
121     g[u][u] = 0; 
122     while(!p.empty())
123     {
124         t = p.front(); p.pop();
125         for(i = 0; i < G[t].size(); ++i)
126         {
127             v = G[t][i];
128             if( !vis[v] )
129             {
130                 vis[v] = 1;
131                 g[u][v] = g[u][t] + 1;
132                 path[u][v] = path[u][t];
133                 path[u][v].push_back(v);
134                 p.push(v);
135             }
136         }
137     }
138 }
139 int GetSum(vector<int> &X,vector<int> &Y,int Pair[])//匹配 
140 {
141     int i,j;
142     Left.clear(); Right.clear(); 
143     for( i = 0; i < X.size(); ++i)
144     {
145         if(s[ X[i] ] == 0) Left.push_back( X[i] );
146     }
147     for( i = 0; i < Y.size(); ++i)
148     {
149         if(s[ Y[i] ] == 1) Right.push_back( Y[i] );
150     }
151     nx = Left.size();
152     ny = Right.size();
153     for( i = 0; i< nx; ++i)
154     {
155         for( j = 0;j< ny; ++j)
156         {
157             int x = Left[i],y = Right[j];
158             map[i][j] = -g[x][y];
159         }
160     }
161     int sum = KM();
162     for(i = 0; i < nx; ++i)
163     {
164         int v = Right[i] ;
165         int u = Left[ linker[i] ];
166         Pair[u] = v; Pair[v] = u;//1 0
167     }
168     return -sum;
169 }
170 void GetAns(int u,int v)
171 {
172     int i, j, k;
173     if(s[u] != 0) swap( u, v);
174     vector<int> &p = path[u][v];
175     for(i = 0; i < p.size(); i = j)
176     {
177         for(j = i; j<p.size() && s[ p[j] ] == 0; ++j); //路上第一个‘1‘
178         if(j == p.size()) break;
179         for(k = j; k > i; --k)
180         {
181             Ans[ans++] = make_pair(p[k], p[k - 1]);
182             swap(s[ p[k] ],s[ p[k-1] ]);
183         }
184     }
185 }
186 int solve(int st)//当前连通分支 
187 {
188     int i, zero = 0, col0 = 0;
189     X.clear(); Y.clear();
190     if(!BFS(st, 0)) return 0;//染色 
191     for(i = 0; i < X.size(); ++i)
192     {
193         if(s[X[i]] == 0) ++zero;
194     }
195     for(i = 0; i < Y.size(); ++i)
196     {
197         if(s[Y[i]] == 0) ++zero; 
198     }
199     int sum1=INF,sum2=INF;
200     if(zero == Y.size() )// ‘0‘ 与 0 的数目相等,X中‘0‘与Y中‘1‘对换 
201     {
202         sum1 = GetSum(X, Y, Pair1);
203     }
204     if(zero == X.size() )// ‘0‘ 与 1 的数目相等,X中‘1‘与Y中‘0‘对换 
205     {
206         sum2 = GetSum(Y, X, Pair2);
207     }
208     if(sum1 == INF && sum2 == INF) return 0;
209     if(sum1 < sum2) Pair = Pair1;
210     else Pair = Pair2;
211     for(i=0;i<X.size(); ++i)
212     {
213         if(Pair[ X[i] ] != -1)  GetAns(X[i], Pair[ X[i] ]);
214     }
215     return 1;
216 }
217 int main()
218 {
219     int i,j,t;
220     scanf("%d", &t);
221     while(t--)
222     {
223         scanf("%d%d%s", &n, &m, s+1);
224         for(i = 1; i <= n; ++i) G[i].clear();
225         for(i = 1; i <= n; ++i)
226         {
227             for(j = 1; j <= n; ++j)
228             {
229                 g[i][j] = INF;
230             }
231         }
232         for(i = 1;i <= m; ++i)
233         {
234             int x,y;
235             scanf("%d%d", &x, &y);
236             G[x].push_back(y);
237             G[y].push_back(x);
238         }
239         for(i = 1; i <= n; ++i)
240             for(j = 1; j <= n; ++j) 
241                 path[i][j].clear();
242         for(i = 1; i <= n; ++i) GetPath(i);//最短路 
243         for(i = 1; i <= n; ++i) 
244         {
245             Pair1[i] = Pair2[i] = col[i] = -1;
246         }
247         bool flag=1;
248         ans = 0;
249         for(i = 1;i <= n; ++i)//对每个连通分支 
250         {
251             if(col[i]==-1&&!solve(i))
252             {
253                 flag = 0; break;
254             }
255         }
256         if(!flag)
257         {
258             puts("-1"); continue;
259         }
260         printf("%d\n",ans);
261         for(i = 0; i< ans ;++i)
262             printf("%d %d\n",Ans[i].first, Ans[i].second);
263     }
264     return 0;
265 }

 

HDU 5740 - Glorious Brilliance

标签:

原文地址:http://www.cnblogs.com/nicetomeetu/p/5722158.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!