Advertisement
qwerty787788

OpenCup XV: Grand Prix of America F

Mar 29th, 2015
587
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 5.44 KB | None | 0 0
  1. import java.io.*;
  2. import java.util.*;
  3.  
  4. public class F {
  5.     FastScanner in;
  6.     PrintWriter out;
  7.  
  8.     class Edge {
  9.         int to;
  10.         double flow, cap;
  11.  
  12.         public Edge(int to, double cap) {
  13.             super();
  14.             this.to = to;
  15.             this.cap = cap;
  16.         }
  17.  
  18.         Edge rev;
  19.  
  20.         @Override
  21.         public String toString() {
  22.             return "Edge [to=" + to + ", flow=" + flow + ", cap=" + cap + "]";
  23.         }
  24.  
  25.     }
  26.  
  27.     class Flow {
  28.         ArrayList<Edge>[] g;
  29.         int[] h;
  30.         int[] cur;
  31.         int[] q;
  32.         int n;
  33.  
  34.         Flow(int n) {
  35.             this.n = n;
  36.             g = new ArrayList[n];
  37.             for (int i = 0; i < n; i++) {
  38.                 g[i] = new ArrayList<>();
  39.             }
  40.             h = new int[n];
  41.             q = new int[n];
  42.             cur = new int[n];
  43.         }
  44.  
  45.         void clean() {
  46.             for (int i = 0; i < n; i++) {
  47.                 for (Edge e : g[i]) {
  48.                     e.flow = 0;
  49.                 }
  50.             }
  51.         }
  52.  
  53.         Edge addEdge(int fr, int to, double cap) {
  54.             Edge e1 = new Edge(to, cap);
  55.             Edge e2 = new Edge(fr, 0);
  56.             e1.rev = e2;
  57.             e2.rev = e1;
  58.             g[fr].add(e1);
  59.             g[to].add(e2);
  60.             return e1;
  61.         }
  62.  
  63.         boolean bfs() {
  64.             int qIt = 0, qSz = 1;
  65.             Arrays.fill(h, -1);
  66.             q[0] = 0;
  67.             h[0] = 0;
  68.             while (qIt < qSz) {
  69.                 int v = q[qIt++];
  70.                 for (Edge e : g[v]) {
  71.                     if (e.flow < e.cap) {
  72.                         if (h[e.to] == -1) {
  73.                             h[e.to] = h[v] + 1;
  74.                             q[qSz++] = e.to;
  75.                         }
  76.                     }
  77.                 }
  78.             }
  79.             return h[n - 1] != -1;
  80.         }
  81.  
  82.         double dfs(int v, double fl) {
  83.             if (v == n - 1 || fl == 0) {
  84.                 return fl;
  85.             }
  86.             for (; cur[v] < g[v].size(); cur[v]++) {
  87.                 Edge e = g[v].get(cur[v]);
  88.                 if (h[e.to] == h[v] + 1) {
  89.                     double add = dfs(e.to, Math.min(e.cap - e.flow, fl));
  90.                     if (add == 0) {
  91.                         continue;
  92.                     }
  93.                     e.flow += add;
  94.                     e.rev.flow -= add;
  95.                     return add;
  96.                 }
  97.             }
  98.             return 0;
  99.         }
  100.  
  101.         double getFlow() {
  102.             double res = 0;
  103.             while (bfs()) {
  104.                 Arrays.fill(cur, 0);
  105.                 while (true) {
  106.                     double xx = dfs(0, Double.MAX_VALUE);
  107.                     if (xx == 0) {
  108.                         break;
  109.                     }
  110.                     res += xx;
  111.                 }
  112.             }
  113.             return res;
  114.         }
  115.     }
  116.  
  117.     void solve() {
  118.         int n = in.nextInt();
  119.         int m = in.nextInt();
  120.         int w = in.nextInt();
  121.         int h = in.nextInt();
  122.         double[] maxColor = new double[m];
  123.         for (int i = 0; i < m; i++) {
  124.             maxColor[i] = in.nextDouble();
  125.         }
  126.         double last = 0;
  127.         double[] ww = new double[n];
  128.         for (int i = 0; i < n - 1; i++) {
  129.             double cur = in.nextDouble();
  130.             ww[i] = cur - last;
  131.             last = cur;
  132.         }
  133.         ww[n - 1] = w - last;
  134.         double[][] min = new double[n][m];
  135.         double[][] max = new double[n][m];
  136.         for (int i = 0; i < n; i++) {
  137.             for (int j = 0; j < m; j++) {
  138.                 min[i][j] = in.nextDouble();
  139.             }
  140.         }
  141.         for (int i = 0; i < n; i++) {
  142.             for (int j = 0; j < m; j++) {
  143.                 max[i][j] = in.nextDouble();
  144.             }
  145.         }
  146.         Flow f = new Flow(2 + n + m);
  147.         Edge[] toSections = new Edge[n];
  148.         for (int i = 0; i < n; i++) {
  149.             toSections[i] = f.addEdge(0, 1 + i, 0);
  150.         }
  151.         for (int i = 0; i < m; i++) {
  152.             double sumColor = 0;
  153.             for (int j = 0; j < n; j++) {
  154.                 sumColor += min[j][i];
  155.             }
  156.             f.addEdge(1 + n + i, 1 + n + m, maxColor[i] - sumColor);
  157.         }
  158.         for (int i = 0; i < n; i++) {
  159.             for (int j = 0; j < m; j++) {
  160.                 f.addEdge(1 + i, 1 + n + j, max[i][j] - min[i][j]);
  161.             }
  162.         }
  163.         double left = 0, right = h;
  164.         double maxH = 0;
  165.         double[] minH = new double[n];
  166.         for (int i = 0; i < n; i++) {
  167.             double sum = 0;
  168.             for (int j = 0; j < m; j++) {
  169.                 sum += min[i][j];
  170.             }
  171.             minH[i] = sum / ww[i];
  172.             maxH = Math.max(maxH, sum / ww[i]);
  173.         }
  174.         for (int it = 0; it < 66; it++) {
  175.             double mid = (left + right) / 2;
  176.             f.clean();
  177.             for (int i = 0; i < n; i++) {
  178.                 double curH = Math.max(minH[i], maxH - mid) - minH[i];
  179.                 toSections[i].cap = curH * ww[i];
  180.             }
  181.             f.getFlow();
  182.             boolean ok = true;
  183.             for (int i = 0; i < n; i++) {
  184.                 if (toSections[i].flow != toSections[i].cap) {
  185.                     ok = false;
  186.                     break;
  187.                 }
  188.             }
  189.             if (ok) {
  190.                 right = mid;
  191.             } else {
  192.                 left = mid;
  193.             }
  194.         }
  195.         out.printf(Locale.US, "%.3f\n", (left + right) / 2);
  196.     }
  197.  
  198.     void run() {
  199.         try {
  200.             in = new FastScanner(new File("F.in"));
  201.             out = new PrintWriter(new File("F.out"));
  202.  
  203.             solve();
  204.  
  205.             out.close();
  206.         } catch (FileNotFoundException e) {
  207.             e.printStackTrace();
  208.         }
  209.     }
  210.  
  211.     void runIO() {
  212.  
  213.         in = new FastScanner(System.in);
  214.         out = new PrintWriter(System.out);
  215.  
  216.         solve();
  217.  
  218.         out.close();
  219.     }
  220.  
  221.     class FastScanner {
  222.         BufferedReader br;
  223.         StringTokenizer st;
  224.  
  225.         public FastScanner(File f) {
  226.             try {
  227.                 br = new BufferedReader(new FileReader(f));
  228.             } catch (FileNotFoundException e) {
  229.                 e.printStackTrace();
  230.             }
  231.         }
  232.  
  233.         public FastScanner(InputStream f) {
  234.             br = new BufferedReader(new InputStreamReader(f));
  235.         }
  236.  
  237.         String next() {
  238.             while (st == null || !st.hasMoreTokens()) {
  239.                 String s = null;
  240.                 try {
  241.                     s = br.readLine();
  242.                 } catch (IOException e) {
  243.                     e.printStackTrace();
  244.                 }
  245.                 if (s == null)
  246.                     return null;
  247.                 st = new StringTokenizer(s);
  248.             }
  249.             return st.nextToken();
  250.         }
  251.  
  252.         boolean hasMoreTokens() {
  253.             while (st == null || !st.hasMoreTokens()) {
  254.                 String s = null;
  255.                 try {
  256.                     s = br.readLine();
  257.                 } catch (IOException e) {
  258.                     e.printStackTrace();
  259.                 }
  260.                 if (s == null)
  261.                     return false;
  262.                 st = new StringTokenizer(s);
  263.             }
  264.             return true;
  265.         }
  266.  
  267.         int nextInt() {
  268.             return Integer.parseInt(next());
  269.         }
  270.  
  271.         long nextLong() {
  272.             return Long.parseLong(next());
  273.         }
  274.  
  275.         double nextDouble() {
  276.             return Double.parseDouble(next());
  277.         }
  278.     }
  279.  
  280.     public static void main(String[] args) {
  281.         new F().runIO();
  282.     }
  283. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement