Advertisement
Guest User

Untitled

a guest
Aug 17th, 2017
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.70 KB | None | 0 0
  1. // Weighted BPM - O(n^3)
  2. // Maximizes the cost
  3. // AC -> ZJU 3425
  4. #include<stdio.h>
  5. #include<string.h>
  6. #include<vector>
  7. #include<algorithm>
  8.  
  9. using namespace std;
  10.  
  11. #define Max(a,b) ((a)>(b)?(a):(b))
  12. #define Min(a,b) ((a)<(b)?(a):(b))
  13. #define N 55             //max number of vertices in one part
  14. #define INF 100000000    //just infinity
  15.  
  16. int cost[N][N];          //cost matrix
  17. int n, max_match;        //n workers and n jobs
  18. int lx[N], ly[N];        //labels of X and Y parts
  19. int xy[N];               //xy[x] - vertex that is matched with x,
  20. int yx[N];               //yx[y] - vertex that is matched with y
  21. bool S[N], T[N];         //sets S and T in algorithm
  22. int slack[N];            //as in the algorithm description
  23. int slackx[N];           //slackx[y] such a vertex, that
  24.                          // l(slackx[y]) + l(y) - w(slackx[y],y) = slack[y]
  25. int prev[N];             //array for memorizing alternating paths
  26.  
  27. void init_labels()
  28. {
  29.     memset(lx, 0, sizeof(lx));
  30.     memset(ly, 0, sizeof(ly));
  31.     for (int x = 0; x < n; x++)
  32.         for (int y = 0; y < n; y++)
  33.             lx[x] = Max(lx[x], cost[x][y]);
  34. }
  35.  
  36. void update_labels()
  37. {
  38.     int x, y, delta = INF;             //init delta as infinity
  39.     for (y = 0; y < n; y++)            //calculate delta using slack
  40.         if (!T[y])
  41.             delta = Min(delta, slack[y]);
  42.     for (x = 0; x < n; x++)            //update X labels
  43.         if (S[x]) lx[x] -= delta;
  44.     for (y = 0; y < n; y++)            //update Y labels
  45.         if (T[y]) ly[y] += delta;
  46.     for (y = 0; y < n; y++)            //update slack array
  47.         if (!T[y])
  48.             slack[y] -= delta;
  49. }
  50.  
  51. void add_to_tree(int x, int prevx)
  52. //x - current vertex,prevx - vertex from X before x in the alternating path,
  53. //so we add edges (prevx, xy[x]), (xy[x], x)
  54. {
  55.     S[x] = true;                    //add x to S
  56.     prev[x] = prevx;                //we need this when augmenting
  57.     for (int y = 0; y < n; y++)    //update slacks, because we add new vertex to S
  58.         if (lx[x] + ly[y] - cost[x][y] < slack[y])
  59.         {
  60.             slack[y] = lx[x] + ly[y] - cost[x][y];
  61.             slackx[y] = x;
  62.         }
  63. }
  64.  
  65. void augment()                         //main function of the algorithm
  66. {
  67.     if (max_match == n) return;        //check wether matching is already perfect
  68.     int x, y, root;                    //just counters and root vertex
  69.     int q[N], wr = 0, rd = 0;          //q - queue for bfs, wr,rd - write and read
  70.                                        //pos in queue
  71.     memset(S, false, sizeof(S));       //init set S
  72.     memset(T, false, sizeof(T));       //init set T
  73.     memset(prev, -1, sizeof(prev));    //init set prev - for the alternating tree
  74.     for (x = 0; x < n; x++)            //finding root of the tree
  75.         if (xy[x] == -1)
  76.         {
  77.             q[wr++] = root = x;
  78.             prev[x] = -2;
  79.             S[x] = true;
  80.             break;
  81.         }
  82.  
  83.     for (y = 0; y < n; y++)            //initializing slack array
  84.     {
  85.         slack[y] = lx[root] + ly[y] - cost[root][y];
  86.         slackx[y] = root;
  87.     }
  88.  
  89.     while (true)                                                        //main cycle
  90.     {
  91.         while (rd < wr)                                                 //building tree with bfs cycle
  92.         {
  93.             x = q[rd++];                                                //current vertex from X part
  94.             for (y = 0; y < n; y++)                                     //iterate through all edges in equality graph
  95.                 if (cost[x][y] == lx[x] + ly[y] &&  !T[y])
  96.                 {
  97.                     if (yx[y] == -1) break;                             //an exposed vertex in Y found, so
  98.                                                                         //augmenting path exists!
  99.                     T[y] = true;                                        //else just add y to T,
  100.                     q[wr++] = yx[y];                                    //add vertex yx[y], which is matched
  101.                                                                         //with y, to the queue
  102.                     add_to_tree(yx[y], x);                              //add edges (x,y) and (y,yx[y]) to the tree
  103.                 }
  104.             if (y < n) break;                                           //augmenting path found!
  105.         }
  106.         if (y < n) break;                                               //augmenting path found!
  107.  
  108.         update_labels();                                                //augmenting path not found, so improve labeling
  109.         wr = rd = 0;                
  110.         for (y = 0; y < n; y++)        
  111.         //in this cycle we add edges that were added to the equality graph as a
  112.         //result of improving the labeling, we add edge (slackx[y], y) to the tree if
  113.         //and only if !T[y] &&  slack[y] == 0, also with this edge we add another one
  114.         //(y, yx[y]) or augment the matching, if y was exposed
  115.             if (!T[y] &&  slack[y] == 0)
  116.             {
  117.                 if (yx[y] == -1)                                        //exposed vertex in Y found - augmenting path exists!
  118.                 {
  119.                     x = slackx[y];
  120.                     break;
  121.                 }
  122.                 else
  123.                 {
  124.                     T[y] = true;                                        //else just add y to T,
  125.                     if (!S[yx[y]])    
  126.                     {
  127.                         q[wr++] = yx[y];                                //add vertex yx[y], which is matched with
  128.                                                                         //y, to the queue
  129.                         add_to_tree(yx[y], slackx[y]);                  //and add edges (x,y) and (y,
  130.                                                                         //yx[y]) to the tree
  131.                     }
  132.                 }
  133.             }
  134.         if (y < n) break;                                               //augmenting path found!
  135.     }
  136.  
  137.     if (y < n)                                                          //we found augmenting path!
  138.     {
  139.         max_match++;                                                    //increment matching
  140.         //in this cycle we inverse edges along augmenting path
  141.         for (int cx = x, cy = y, ty; cx != -2; cx = prev[cx], cy = ty)
  142.         {
  143.             ty = xy[cx];
  144.             yx[cy] = cx;
  145.             xy[cx] = cy;
  146.         }
  147.         augment();                                                      //recall function, go to step 1 of the algorithm
  148.     }
  149. }//end of augment() function
  150.  
  151. int hungarian()
  152. {
  153.     int ret = 0;                      //weight of the optimal matching
  154.     max_match = 0;                    //number of vertices in current matching
  155.     memset(xy, -1, sizeof(xy));    
  156.     memset(yx, -1, sizeof(yx));
  157.     init_labels();                    //step 0
  158.     augment();                        //steps 1-3
  159.     for (int x = 0; x < n; x++)       //forming answer there
  160.         ret += cost[x][xy[x]];
  161.     return ret;
  162. }
  163.  
  164. int student[35][10005];
  165.  
  166. void build(int id,int k)
  167. {
  168.     int i;
  169.     char ss[10];
  170.     vector<int> vi;
  171.     int fr[30]={0};
  172.     for(i=0;i<k;i++)       
  173.     {
  174.         scanf("%s",ss),student[id][i]=ss[0]-'A';
  175.         if(!fr[student[id][i]])
  176.             fr[student[id][i]]=1,vi.push_back(student[id][i]);
  177.     }
  178.     sort(vi.begin(),vi.end());
  179.     for(i=0;i<vi.size();i++)
  180.         fr[vi[i]]=i;
  181.     for(i=0;i<k;i++)
  182.         student[id][i]=fr[student[id][i]];
  183. }
  184.  
  185. int main()
  186. {
  187.     int t;
  188.     scanf("%d",&t);
  189.     while(t--)
  190.     {
  191.         int m,k,i,j;
  192.         scanf("%d%d%d",&k,&n,&m);
  193.         build(0,k);
  194.         for(i=1;i<=m;i++)
  195.         {
  196.             build(i,k);
  197.             memset(cost,0,sizeof(cost));
  198.             for(j=0;j<k;j++)
  199.                 cost[student[i][j]][student[0][j]]++;
  200.             int res=hungarian();
  201.             printf("%.4lf\n",res/(k+0.0));
  202.         }
  203.     }
  204.     return 0;
  205. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement