看上去和修车一模一样的东西 可是数据范围大太多铁定要T
然后听说了动态加边这个东西感觉虽然不能改变时间复杂度 但是还是很有用的样子
每次增广后找到该次的厨师给它新增一个点 然后费用逐步递增 (最后一个菜贡献1倍 倒数第二个贡献两倍)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<deque>
#define SF scanf
#define PF printf
using namespace std;
typedef long long LL;
const int MAXN = 100000;
const int INF = 0x3f3f3f3f;
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = 10*x + ch-'0'; ch = getchar(); }
return x*f;
}
int c[MAXN+10], tot, t[50][110], now[MAXN+10];
int n, m, S, T, ans, ecnt = 2, ncnt;
queue <int> q;
struct MCMF {
int N, M;
int d[MAXN+10], p[MAXN+10], a[MAXN+10], inq[MAXN+10];
struct Node {
int u, v, c, cost, next;
} Edge[MAXN*60+10];
int adj[MAXN+10];
void addedge(int u, int v, int c, int wt) {
Node &e = Edge[ecnt];
e.u = u; e.v = v; e.c = c; e.cost = wt;
e.next = adj[u]; adj[u] = ecnt++;
}
void add(int u, int v, int c, int cost) {
addedge(u, v, c, cost); addedge(v, u, 0, -cost);
}
bool SPFA(int s, int t, int &Flow, int &Cost) {
memset(d, 0x3f, sizeof(d));
d[s] = 0; a[s] = INF; p[s] = 0; inq[s] = 1;
q.push(s);
while(!q.empty()) {
int u = q.front(); q.pop();
inq[u] = 0;
for(int i = adj[u]; i; i = Edge[i].next) {
Node &e = Edge[i];
int v = e.v, c = e.c, wt = e.cost;
if(c && d[v] > d[u] + wt) {
d[v] = d[u] + wt;
a[v] = min(a[u], c);
p[v] = i;
if(!inq[v]) {
inq[v] = true;
q.push(v);
}
}
}
}
if(d[t] == INF) return false;
return true;
}
void extend() {
int A, B;
for(int i = T; i ^ S; i = Edge[p[i]].u) {
Edge[p[i]].c -= a[T];
Edge[p[i]^1].c += a[T];
if(i <= m && i >= 1) A = i;
if(i != T && i > m) B = i;
}
++now[A];
add(A, ++ncnt, 1, 0);
for(int i = 1; i <= n; i++)
add(ncnt, m+i, 1, (now[A]+1) * t[i][A]);
ans += a[T] * d[T];
}
int Mincost(int s, int t) {
int Flow = 0, Cost = 0;
while(SPFA(s, t, Flow, Cost))
extend();
return Cost;
}
} sap;
int main() {
S = 0; T = MAXN+1;
n = read(); m = read();
for(int i = 1; i <= n; i++) tot += (c[i] = read());
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
t[i][j] = read();
for(int i = 1; i <= m; i++) sap.add(S, ++ncnt, INF, 0);
for(int i = 1; i <= n; i++) sap.add(++ncnt, T, c[i], 0);
for(int i = 1; i <= m; i++) {
sap.add(i, ++ncnt, 1, 0);
for(int j = 1; j <= n; j++)
sap.add(ncnt, m+j, 1, t[j][i]);
}
sap.Mincost(S, T);
PF("%d", ans);
}