Test address: Delicacy Festival
Method: this problem needs to use cost flow + Split point + dynamic edge.
First of all, after submitting this question, I have reached 150AC in BZOJ. I would like to celebrate it~
Well, back to the topic, we found that this topic is exactly the same as BZOJ1070 except for the data range. See my writing for the modeling method BZOJ1070 explanation.
When the data range of this problem becomes larger, we will obviously time out when we start to build all the graphs. Therefore, we use the optimization method of dynamic edge adding, that is, only when we use it, can we build the corresponding parts of the graphs.
In the beginning, we only connected the reciprocal first dish of each chef to the edge between the dishes. We found that each enlargement is actually equivalent to one more dish made by one chef, while other chefs on the way of enlargement have changed one dish to make, so we only need to reserve one more enlargement space for each chef, so that the number of points in the figure will be greatly reduced, so that we can It's through.
Here is my code:
#include <bits/stdc++.h>
using namespace std;
const int inf=1000000000;
int n,m,S,T,totid=0;
int t[45][110],X[10010],Y[10010],first[10010]={0},tot=1;
int dis[10010],laste[10010],last[10010];
bool vis[10010]={0};
queue<int> Q;
struct edge
{
int v,next,f,c;
}e[2000010];
void insert(int a,int b,int f,int c)
{
e[++tot].v=b,e[tot].next=first[a],e[tot].f=f,e[tot].c=c,first[a]=tot;
e[++tot].v=a,e[tot].next=first[b],e[tot].f=0,e[tot].c=-c,first[b]=tot;
}
void init()
{
scanf("%d%d",&n,&m);
S=1,T=2,totid=2;
for(int i=1;i<=n;i++)
{
int p;
scanf("%d",&p);
insert(++totid,T,p,0);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&t[i][j]);
for(int i=1;i<=m;i++)
{
X[++totid]=i,Y[totid]=1;
insert(S,totid,1,0);
for(int j=1;j<=n;j++)
insert(totid,j+2,1,t[j][i]);
}
}
bool spfa()
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=totid;i++)
dis[i]=inf;
dis[S]=0;
vis[S]=1;
Q.push(S);
while(!Q.empty())
{
int v=Q.front();Q.pop();
for(int i=first[v];i;i=e[i].next)
if (e[i].f&&dis[e[i].v]>dis[v]+e[i].c)
{
dis[e[i].v]=dis[v]+e[i].c;
laste[e[i].v]=i;
last[e[i].v]=v;
if (!vis[e[i].v]) vis[e[i].v]=1,Q.push(e[i].v);
}
vis[v]=0;
}
return dis[T]!=inf;
}
void mincost()
{
int minc=0;
while(spfa())
{
int x=T,maxf=inf;
while(x!=S)
{
maxf=min(maxf,e[laste[x]].f);
x=last[x];
}
x=T;
while(x!=S)
{
e[laste[x]].f-=maxf;
e[laste[x]^1].f+=maxf;
if (last[x]==S)
{
X[++totid]=X[x],Y[totid]=Y[x]+1;
insert(S,totid,1,0);
for(int i=1;i<=n;i++)
insert(totid,i+2,1,t[i][X[totid]]*Y[totid]);
}
x=last[x];
}
minc+=maxf*dis[T];
}
printf("%d",minc);
}
int main()
{
init();
mincost();
return 0;
}