• HDU 5740


    题意:

        给出已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
    ",ans);
    261         for(i = 0; i< ans ;++i)
    262             printf("%d %d
    ",Ans[i].first, Ans[i].second);
    263     }
    264     return 0;
    265 }
    我自倾杯,君且随意
  • 相关阅读:
    数学符号表
    对比深度学习十大框架:TensorFlow最流行但并不是最好
    支持向量机通俗导论(理解SVM的三层境界)
    Annotation
    Struts2的拦截器
    DLL文件的引用
    JS引擎
    Windows窗口的创建
    解决构造器多参数的设计问题
    静态工厂对比构造器之优缺点
  • 原文地址:https://www.cnblogs.com/nicetomeetu/p/5722158.html
Copyright © 2020-2023  润新知