题解:

果然是神题,orz!!!

搬运题解:

做过修车就好办了。这个题仅仅是数据范围变大了一坨。建图就不说了,主要是动态加边。倒过来做,因为一个厨师最后一个菜做的时间是不会影响到其他菜的时间 的。

而且每一个厨师确定了最后一个菜才能去想倒数第二个菜是什么。所以每跑一次SPFA,就回来看看是哪个厨师做的菜,然后在多加一个点限制一下流量,将 这个点连向所有的菜。

实现很有技巧!!!我参考了lyd的代码

代码:

  1 #include<cstdio>
  2 
  3 #include<cstdlib>
  4 
  5 #include<cmath>
  6 
  7 #include<cstring>
  8 
  9 #include<algorithm>
 10 
 11 #include<iostream>
 12 
 13 #include<vector>
 14 
 15 #include<map>
 16 
 17 #include<set>
 18 
 19 #include<queue>
 20 
 21 #include<string>
 22 
 23 #define inf 1000000000
 24 
 25 #define maxn 200000+5
 26 
 27 #define maxm 2000000+5
 28 
 29 #define eps 1e-10
 30 
 31 #define ll long long
 32 
 33 #define pa pair<int,int>
 34 
 35 #define for0(i,n) for(int i=0;i<=(n);i++)
 36 
 37 #define for1(i,n) for(int i=1;i<=(n);i++)
 38 
 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 40 
 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 42 
 43 #define for4(i,x) for(int i=head[x],y;i;i=e[i].next)
 44 
 45 #define for5(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
 46 
 47 #define mod 1000000007
 48 
 49 using namespace std;
 50 
 51 inline int read()
 52 
 53 {
 54 
 55     int x=0,f=1;char ch=getchar();
 56 
 57     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 58 
 59     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 60 
 61     return x*f;
 62 
 63 }
 64 int n,m,k,cnt[maxn],now[maxn],cntcnt,mincost,maxflow,tot=1,s,t,a[1000],b[1000][1000],sum,c[maxn],head[maxn],d[maxn],from[2*maxm];
 65 
 66 bool v[maxn];
 67 
 68 queue<int>q;
 69 
 70 struct edge{int from,go,next,v,c;}e[2*maxm];
 71 
 72 void add(int x,int y,int v,int c)
 73 
 74 {
 75 
 76     e[++tot]=(edge){x,y,head[x],v,c};head[x]=tot;
 77 
 78     e[++tot]=(edge){y,x,head[y],0,-c};head[y]=tot;
 79 
 80 }
 81 
 82 bool spfa()
 83 
 84 {
 85 
 86     for (int i=0;i<=cntcnt;i++){v[i]=0;d[i]=inf;}
 87 
 88     q.push(s);d[s]=0;v[s]=1;
 89 
 90     while(!q.empty())
 91 
 92     {
 93 
 94         int x=q.front();q.pop();v[x]=0;
 95 
 96         for (int i=head[x],y;i;i=e[i].next)
 97 
 98          if(e[i].v&&d[x]+e[i].c<d[y=e[i].go])
 99 
100          {
101 
102             d[y]=d[x]+e[i].c;from[y]=i;
103 
104             if(!v[y]){v[y]=1;q.push(y);}
105 
106          }
107 
108     }
109 
110     return d[t]!=inf;
111 
112 }
113 
114 void update()
115 
116 {
117 
118     for(int i=from[t];i!=s;i=from[e[i].from])
119     {
120         e[i].v--;e[i^1].v++;
121     }
122     mincost+=d[t];sum--;
123 
124 }
125 
126 int main()
127 
128 {
129 
130     freopen("input.txt","r",stdin);
131 
132     freopen("output.txt","w",stdout);
133 
134     n=read();m=read();
135     for1(i,n)a[i]=read(),sum+=a[i];
136     for1(i,n)for1(j,m)b[i][j]=read();
137     s=0;t=n+1;cntcnt=n+m+1;
138     for1(i,n)add(s,i,a[i],0);
139     for1(i,m)add(n+1+i,t,1,0),cnt[i]=1,now[i]=tot;
140     for1(i,n)for1(j,m)add(i,n+1+j,1,b[i][j]);
141     while(sum)
142     {
143         if(spfa())update();
144         for1(i,m)
145         if(!e[now[i]^1].v)
146         {
147             add(++cntcnt,t,1,0),now[i]=tot,cnt[i]++;
148             for1(j,n)add(j,cntcnt,1,cnt[i]*b[j][i]);
149             break;
150         }
151     }
152     cout<<mincost<<endl;
153 
154     return 0;
155 
156 }  
View Code

相关文章:

  • 2022-03-05
  • 2021-08-12
  • 2021-10-12
  • 2021-12-30
  • 2021-05-18
  • 2021-11-05
  • 2021-08-19
猜你喜欢
  • 2021-07-31
  • 2021-07-14
  • 2021-06-04
  • 2021-05-22
相关资源
相似解决方案