最大费用最大流
需要开一个源点,次源点,汇点,然后把电影当成点并拆开。
源点到次源点连一条容量k费用0的边,次源点到每个电影拆开的点的一边都连一条容量1费用0的边,电影拆开的点两边连一条容量1费用为w的
边,然后如果时间允许就在电影拆开的点的出点和另一个电影的入点连一条容量1费用-W的边,最后每个电影的出点和汇点连容量1费用0的边。
跑最大费用最大流。。
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define full(a, b) memset(a, b, sizeof a)
#define FAST_IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;
typedef long long ll;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
int ret = 0, w = 0; char ch = 0;
while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
while(isdigit(ch)) ret = (ret << 3) + (ret << 1) + (ch ^ 48), ch = getchar();
return w ? -ret : ret;
}
inline int gcd(int a, int b){ return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
template <typename T>
inline T max(T x, T y, T z){ return max(max(x, y), z); }
template <typename T>
inline T min(T x, T y, T z){ return min(min(x, y), z); }
template <typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){
A ans = 1;
for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
return ans;
}
const int N = 5000;
int _, n, m, k, w, cnt, s, t, head[N<<1], d[N<<1], incf[N<<1], pre[N<<1];
bool inq[N<<1];
struct Edge { int v, next, f, cost; } edge[N<<2];
struct Videos{ int l, r, w, op; } vi[N];
void addEdge(int a, int b, int c, int d){
edge[cnt].v = b, edge[cnt].f = c, edge[cnt].cost = d, edge[cnt].next = head[a], head[a] = cnt ++;
edge[cnt].v = a, edge[cnt].f = 0, edge[cnt].cost = -d, edge[cnt].next = head[b], head[b] = cnt ++;
}
void build(){
cnt = 0;
full(head, -1), full(pre, -1), full(incf, INF);
}
bool spfa(){
queue<int> q;
full(d, 0xcf), full(inq, false);
inq[s] = true, d[s] = 0, incf[s] = INF;
q.push(s);
while(!q.empty()){
int cur = q.front(); q.pop(); inq[cur] = false;
for(int i = head[cur]; i != -1; i = edge[i].next){
int u = edge[i].v;
if(edge[i].f > 0 && d[u] < d[cur] + edge[i].cost){
d[u] = d[cur] + edge[i].cost;
incf[u] = min(incf[cur], edge[i].f);
pre[u] = i;
if(!inq[u]) inq[u] = true, q.push(u);
}
}
}
return d[t] != 0xcfcfcfcf;
}
int mcmf(){
int ret = 0;
while(spfa()){
int x = t;
while(x != s){
int i = pre[x];
edge[i].f -= incf[t], edge[i^1].f += incf[t];
x = edge[i^1].v;
}
ret += d[t] * incf[t];
}
return ret;
}
int main(){
for(_ = read(); _; _ --){
build();
n = read(), m = read(), k = read(), w = read();
for(int i = 1; i <= m; i ++){
vi[i].l = read(), vi[i].r = read(), vi[i].w = read(), vi[i].op = read();
}
s = 2 * m + 1, t = 2 * m + 3;
addEdge(s, s + 1, k, 0);
for(int i = 1; i <= m; i ++){
addEdge(s + 1, i, 1, 0), addEdge(i, i + m, 1, vi[i].w);
}
for(int i = 1; i <= m; i ++){
for(int j = 1; j <= m; j ++){
if(vi[i].r <= vi[j].l)
addEdge(i + m, j, 1, vi[i].op == vi[j].op ? -w : 0);
}
}
for(int i = 1; i <= m; i ++) addEdge(i + m, t, 1, 0);
printf("%d
", mcmf());
}
return 0;
}