qwerty787788

Multiassignment problem

Dec 22nd, 2012
235
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 9.22 KB | None | 0 0
  1.  
  2. import java.io.*;
  3. import java.util.*;
  4.  
  5. public class MinCostMaxFlow {
  6.     FastScanner in;
  7.     PrintWriter out;
  8.  
  9.     class MinCostMaxFlowGraph {
  10.         int n;
  11.         ArrayList<Edge>[] g;
  12.  
  13.         class Edge {
  14.             int from, to;
  15.             long cap, flow, cost;
  16.             Edge rev;
  17.  
  18.             public Edge(int from, int to, long cap, long flow, long cost) {
  19.                 super();
  20.                 this.from = from;
  21.                 this.to = to;
  22.                 this.cap = cap;
  23.                 this.flow = flow;
  24.                 this.cost = cost;
  25.             }
  26.         }
  27.  
  28.         class Vertex implements Comparable<Vertex> {
  29.             int v;
  30.             Edge e;
  31.             long d;
  32.  
  33.             public Vertex(int v) {
  34.                 super();
  35.                 this.v = v;
  36.             }
  37.  
  38.             @Override
  39.             public int compareTo(Vertex o) {
  40.                 return d < o.d ? -1 : d > o.d ? 1 : v - o.v;
  41.             }
  42.  
  43.         }
  44.  
  45.         public MinCostMaxFlowGraph(int n) {
  46.             super();
  47.             this.n = n;
  48.             g = new ArrayList[n];
  49.             for (int i = 0; i < n; i++)
  50.                 g[i] = new ArrayList<Edge>();
  51.         }
  52.  
  53.         public void addEdge(int fr, int to, int cap, long cost) {
  54.             Edge e1 = new Edge(fr, to, cap, 0, cost);
  55.             Edge e2 = new Edge(to, fr, 0, 0, -cost);
  56.             e1.rev = e2;
  57.             e2.rev = e1;
  58.             g[fr].add(e1);
  59.             g[to].add(e2);
  60.         }
  61.  
  62.         public long[] getMinCostMaxFlow(int source, int target) {
  63.             long[] h = new long[n];
  64.             for (boolean changed = true; changed;) {
  65.                 changed = false;
  66.                 for (int i = 0; i < n; i++) {
  67.                     for (Edge e : g[i]) {
  68.                         if (e.cap > 0 && h[e.to] > h[e.from] + e.cost) {
  69.                             h[e.to] = h[e.from] + e.cost;
  70.                             changed = true;
  71.                         }
  72.                     }
  73.                 }
  74.             }
  75.             Vertex[] vertices = new Vertex[n];
  76.             long[] d = new long[n];
  77.             for (int i = 0; i < vertices.length; i++) {
  78.                 vertices[i] = new Vertex(i);
  79.             }
  80.             int flow = 0;
  81.             long cost = 0;
  82.             while (true) {
  83.                 dijkstra(source, vertices, d, h);
  84.                 if (d[target] == Long.MAX_VALUE) {
  85.                     break;
  86.                 }
  87.                 long addFlow = Long.MAX_VALUE;
  88.                 Vertex v = vertices[target];
  89.                 while (v != vertices[source]) {
  90.                     addFlow = Math.min(addFlow, v.e.cap - v.e.flow);
  91.                     v = vertices[v.e.from];
  92.                 }
  93.                 cost += (d[target] + h[target] - h[source]) * addFlow;
  94.                 flow += addFlow;
  95.                 v = vertices[target];
  96.                 while (v != vertices[source]) {
  97.                     v.e.flow += addFlow;
  98.                     v.e.rev.flow -= addFlow;
  99.                     v = vertices[v.e.from];
  100.                 }
  101.                 for (int i = 0; i < n; i++) {
  102.                     h[i] += d[i] == Long.MAX_VALUE ? 0 : d[i];
  103.                 }
  104.             }
  105.             return new long[] { flow, cost };
  106.         }
  107.  
  108.         void dijkstra(int source, Vertex[] vertices, long[] d, long[] h) {
  109.             TreeSet<Vertex> ts = new TreeSet<Vertex>();
  110.             Arrays.fill(d, Long.MAX_VALUE);
  111.             for (int i = 0; i < vertices.length; i++) {
  112.                 vertices[i].d = Long.MAX_VALUE;
  113.             }
  114.             d[source] = 0;
  115.             vertices[source].d = 0;
  116.             ts.add(vertices[source]);
  117.             while (!ts.isEmpty()) {
  118.                 Vertex v = ts.pollFirst();
  119.                 for (Edge e : g[v.v]) {
  120.                     if (e.flow >= e.cap) {
  121.                         continue;
  122.                     }
  123.                     if (d[e.to] == Long.MAX_VALUE
  124.                             || d[e.to] > d[e.from] + e.cost + h[e.from]
  125.                                     - h[e.to]) {
  126.                         if (e.cost + h[e.from] - h[e.to] < 0) {
  127.                             throw new AssertionError();
  128.                         }
  129.                         if (ts.contains(vertices[e.to])) {
  130.                             ts.remove(vertices[e.to]);
  131.                         }
  132.                         d[e.to] = d[e.from] + e.cost + h[e.from] - h[e.to];
  133.                         vertices[e.to].d = d[e.to];
  134.                         vertices[e.to].e = e;
  135.                         ts.add(vertices[e.to]);
  136.                     }
  137.                 }
  138.             }
  139.         }
  140.     }
  141.  
  142.     class Kuhn {
  143.         int n;
  144.         boolean[] used;
  145.         int[] left;
  146.  
  147.         ArrayList<Integer>[] g;
  148.  
  149.         public void addEdge(int fr, int to) {
  150.             g[fr].add(to);
  151.         }
  152.  
  153.         public Kuhn(int n) {
  154.             super();
  155.             this.n = n;
  156.             used = new boolean[n];
  157.             left = new int[n];
  158.             g = new ArrayList[n];
  159.             for (int i = 0; i < n; i++)
  160.                 g[i] = new ArrayList<Integer>();
  161.         }
  162.  
  163.         boolean tryKuhn(int v) {
  164.             if (used[v])
  165.                 return false;
  166.             used[v] = true;
  167.             for (int i = 0; i < g[v].size(); ++i) {
  168.                 int to = g[v].get(i);
  169.                 if (left[to] == -1 || tryKuhn(left[to])) {
  170.                     left[to] = v;
  171.                     return true;
  172.                 }
  173.             }
  174.             return false;
  175.         }
  176.  
  177.         boolean solve() {
  178.             Arrays.fill(left, -1);
  179.             for (int v = 0; v < n; ++v) {
  180.                 Arrays.fill(used, false);
  181.                 tryKuhn(v);
  182.             }
  183.  
  184.             for (int i = 0; i < n; i++)
  185.                 if (left[i] == -1)
  186.                     return false;
  187.             return true;
  188.         }
  189.  
  190.     }
  191.  
  192.     void solve() {
  193.         int n = in.nextInt();
  194.         int k = in.nextInt();
  195.         MinCostMaxFlowGraph mm = new MinCostMaxFlowGraph(2 * (n + 1));
  196.         for (int i = 0; i < n; i++) {
  197.             for (int j = 0; j < n; j++) {
  198.                 mm.addEdge(i, j + n, 1, in.nextInt());
  199.             }
  200.         }
  201.         for (int i = 0; i < n; i++)
  202.             mm.addEdge(2 * n, i, k, 0);
  203.         for (int i = n; i < 2 * n; i++)
  204.             mm.addEdge(i, 2 * n + 1, k, 0);
  205.         out.println(mm.getMinCostMaxFlow(2 * n, 2 * n + 1)[1]);
  206.         Kuhn kuhn = new Kuhn(n);
  207.         for (int i = 0; i < n; i++)
  208.             for (MinCostMaxFlowGraph.Edge e : mm.g[i]) {
  209.                 if (e.flow > 0)
  210.                     kuhn.addEdge(i, e.to - n);
  211.             }
  212.         for (int i = 0; i < k; i++) {
  213.             kuhn.solve();
  214.             int[] ans = new int[n];
  215.             for (int j = 0; j < n; j++) {
  216.                 ans[kuhn.left[j]] = j;
  217.             }
  218.             for (int j = 0; j < n; j++)
  219.                 out.print((ans[j] + 1) + " ");
  220.             for (int j = 0; j < n; j++)
  221.                 for (int kk = 0; kk < kuhn.g[j].size(); kk++)
  222.                     if (kuhn.g[j].get(kk) == ans[j])
  223.                         kuhn.g[j].remove(kk);
  224.             out.println();
  225.         }
  226.     }
  227.  
  228.     void run() {
  229.         try {
  230.             in = new FastScanner(new File("multiassignment.in"));
  231.             out = new PrintWriter(new File("multiassignment.out"));
  232.  
  233.             solve();
  234.  
  235.             out.close();
  236.         } catch (FileNotFoundException e) {
  237.             e.printStackTrace();
  238.         }
  239.     }
  240.  
  241.     void runIO() {
  242.  
  243.         in = new FastScanner(System.in);
  244.         out = new PrintWriter(System.out);
  245.  
  246.         solve();
  247.  
  248.         out.close();
  249.     }
  250.  
  251.     class FastScanner {
  252.         BufferedReader br;
  253.         StringTokenizer st;
  254.  
  255.         public FastScanner(File f) {
  256.             try {
  257.                 br = new BufferedReader(new FileReader(f));
  258.             } catch (FileNotFoundException e) {
  259.                 e.printStackTrace();
  260.             }
  261.         }
  262.  
  263.         public FastScanner(InputStream f) {
  264.             br = new BufferedReader(new InputStreamReader(f));
  265.         }
  266.  
  267.         String next() {
  268.             while (st == null || !st.hasMoreTokens()) {
  269.                 String s = null;
  270.                 try {
  271.                     s = br.readLine();
  272.                 } catch (IOException e) {
  273.                     e.printStackTrace();
  274.                 }
  275.                 if (s == null)
  276.                     return null;
  277.                 st = new StringTokenizer(s);
  278.             }
  279.             return st.nextToken();
  280.         }
  281.  
  282.         boolean hasMoreTokens() {
  283.             while (st == null || !st.hasMoreTokens()) {
  284.                 String s = null;
  285.                 try {
  286.                     s = br.readLine();
  287.                 } catch (IOException e) {
  288.                     e.printStackTrace();
  289.                 }
  290.                 if (s == null)
  291.                     return false;
  292.                 st = new StringTokenizer(s);
  293.             }
  294.             return true;
  295.         }
  296.  
  297.         int nextInt() {
  298.             return Integer.parseInt(next());
  299.         }
  300.  
  301.         long nextLong() {
  302.             return Long.parseLong(next());
  303.         }
  304.     }
  305.  
  306.     public static void main(String[] args) {
  307.         new MinCostMaxFlow().run();
  308.     }
  309. }
Advertisement
Add Comment
Please, Sign In to add comment