zoukankan      html  css  js  c++  java
  • NOI2012 美食节 解题报告

      首先看看BZOJ 1040《修车》,如果没有做,请做完后再来看这道题。

      我们惊喜地发现,这道题的题意跟 修车 基本一样。很可惜,数据范围。。。

      我试了一下直接修改 修车 的代码,建成2+n+p*m个点,n*m*p条边的有向图,对其求费用流,时间复杂度O((2+n+p*m)^2*(n*m*p)),实际测试中得到40分。

      既然不能做这么庞大的图的网络流,我们考虑动态加点。

      

      刚开始连边:

      

      现在,所有厨师都闲着,那我们把每位厨师做倒数第一道菜的边连向N个点。

      

      然后做费用流。

      在增广的过程中,如果k厨师做倒数第i个菜连到汇点满流,则每个菜对k厨师做倒数第i+1个菜连一条边,流量为1,权值为(i+1) * t[][k]。这样做到动态加边,避免因为边数过多导致超时。

      谢谢HSJMDMG大神在其博客中详细地写到如何动态加点

      http://hi.baidu.com/hsjm_mushroom/item/5927e18558e85855840fab8e

      下面是在BZOJ中通过的代码(实际测试中只获得了80%的分数,待优化):

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 
      5 #define N 803
      6 #define M 102
      7 #define K 327680
      8 
      9 using namespace std;
     10 
     11 struct EDGE{
     12     int adj, flow, cost, next;
     13 } edge[K];
     14 int n, m, k, p[N], S, T, dist[K], pre[K], prev[K], top;
     15 int t[N][M], gh[K], q[K], v[K], cnt[M];
     16 
     17 void addedge(int x, int y, int flow, int cost)
     18 {
     19     edge[++top].adj = y;
     20     edge[top].flow = flow;
     21     edge[top].cost = cost;
     22     edge[top].next = gh[x];
     23     gh[x] = top;
     24     edge[++top].adj = x;
     25     edge[top].flow = 0;
     26     edge[top].cost = -cost;
     27     edge[top].next = gh[y];
     28     gh[y] = top;
     29 }
     30 
     31 int inc(int &x) {return (x += 1) %= K;}
     32 
     33 int spfa()
     34 {
     35     int head = -1, tail = 0;
     36     memset(dist, 0x7f, sizeof(dist[0])*(k*m+n+3));
     37     q[0] = S; dist[S] = 0;
     38     while (head != tail)
     39     {
     40         int h = q[inc(head)]; v[h] = 0;
     41         for (int p = gh[h]; p; p=edge[p].next)
     42             if (edge[p].flow && edge[p].cost + dist[h] < dist[edge[p].adj])
     43             {
     44                 dist[edge[p].adj] = edge[p].cost + dist[h];
     45                 pre[edge[p].adj] = h;
     46                 prev[edge[p].adj] = p;
     47                 if (!v[edge[p].adj])
     48                 {
     49                     v[edge[p].adj] = 1;
     50                     q[inc(tail)] = edge[p].adj;
     51                 }
     52             }
     53     }
     54     return dist[T] <= 0x7f000000;
     55 }
     56 
     57 int flow()
     58 {
     59     int m = 0x7f7f7f7f, qans = 0;
     60     for (int i=T;i!=S;i=pre[i])
     61         if (edge[prev[i]].flow < m) m = edge[prev[i]].flow;
     62     for (int i=T;i!=S;i=pre[i])
     63     {
     64         edge[prev[i]].flow -= m;
     65         edge[prev[i]^1].flow += m;
     66         qans += m * edge[prev[i]].cost;
     67     }
     68     int ptr = pre[T] + 1;
     69     int x = pre[T] - 2 - n;
     70     ((x -= 1) /= k) += 1;
     71     if (cnt[x]==k) return qans;
     72     ++cnt[x];
     73     for (int i=1;i<=n;i++)
     74         addedge(i+2, 2+n+(x-1)*k+cnt[x], 1, t[i][x] * (cnt[x]));
     75     return qans;
     76 }
     77 
     78 int main()
     79 {
     80 #ifndef ONLINE_JUDGE
     81     freopen("delicacy.in","r",stdin);
     82     freopen("delicacy.out","w",stdout);
     83 #endif
     84     scanf("%d%d",&n,&m);
     85     k = 0;
     86     for (int i=1;i<=n;i++)
     87     {
     88         scanf("%d",&p[i]);
     89         k += p[i];
     90     }
     91     for (int i=1;i<=m;i++)
     92         cnt[i] = 1;
     93     for (int i=1;i<=n;i++)
     94         for (int l1=1;l1<=m;l1++)
     95             scanf("%d",&t[i][l1]);
     96     S = 1, T = 2; top = 1;
     97     for (int i=1;i<=n;i++)
     98         addedge(S, i+2, p[i], 0);
     99     for (int i=0;i<m;i++)
    100         for (int j=1;j<=k;j++)
    101             addedge(i*k+j+2+n, T, 1, 0);
    102     for (int l=1;l<=n;l++)
    103         for (int i=0;i<m;i++)
    104             addedge(l+2, i*k+3+n, 1, t[l][i+1]);
    105     int ans = 0;
    106     while (spfa())
    107         ans += flow();
    108     printf("%d
    ",ans);
    109     return 0;
    110 }
    View Code: delicacy.cpp
  • 相关阅读:
    如何更好地理解闭包
    抽象类和抽象方法以及和接口区别
    JavaScript中如何理解如何理解Array.apply(null, {length:5})
    Java线程中的同步
    Python前世今生以及种类、安装环境
    大数据中的用户画像
    Java web每天学之Servlet工作原理详情解析
    Go语言操作MySQL数据库
    老集群RAC双网卡绑定
    nmcli配置ipv6
  • 原文地址:https://www.cnblogs.com/africamonkey/p/3748118.html
Copyright © 2011-2022 走看看