HDU-6437 Videos
题意:一天有n个小时,现在有m场电影,每场电影有一个愉悦值,有k个人,电影分2种类型A, B, 并且每一场电影只能一个人看, 一个人可以看无数次电影, 只要时间足够, 但是连续看同一种电影会减少愉悦值W点。现在要求所有人总的愉悦值加起来最大。
题解:
网络流建图,先把每个点拆成2个点, u 和 u‘ , 在u和u’中间连一条流量为1,费用为0的边, 现在我们规定 一个点的 复制点只能和本体链接, 只能由复制点往外流, 然后别的点流入只能留到本体。
也就是 假设 存在 u, v2个点, 这2个点之间可以存在边且为u->v 那么连线方式就为 u -> u' -> v -> v'。
因为每个电影看的人最多是1, 所以 u - > u' 的流量为1。
s -> s'的流量为k。
然后我们把s‘和所有的电影建边 流量为1, 花费为电影获得的愉悦值
然后把所有电影与t建边 流量为1,花费为0
然后我们把看完一场电影之后可以去看另一场电影的2个点建边,花费为下一次电影的愉悦值 - (是否为同一种类电影)* W。
由于是需要最大的愉悦值, 我们把花费取反, 然后跑费用流。 最后把答案取反。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 14 typedef pair<int,int> pll; 15 const int INF = 0x3f3f3f3f; 16 const LL mod = (int)1e9+7; 17 const int N = 1e5; 18 const int M = 2005; 19 int head[M], to[N], ct[N], w[N], nt[N]; 20 int d[M], vis[M]; 21 int pre[M], id[N]; 22 int n, m, s, t, tot; 23 24 void add(int u, int v, int val, int cost){ 25 to[tot] = v; 26 ct[tot] = -cost; 27 w[tot] = val; 28 nt[tot] = head[u]; 29 head[u] = tot++; 30 31 to[tot] = u; 32 ct[tot] = cost; 33 w[tot] = 0; 34 nt[tot] = head[v]; 35 head[v] = tot++; 36 } 37 void init(){ 38 memset(head,-1,sizeof(head)); 39 tot = 0; 40 } 41 int spfa(){ 42 queue<int> q; 43 memset(d, INF, sizeof(d)); 44 memset(vis, 0, sizeof(vis)); 45 memset(pre, -1, sizeof(vis)); 46 d[s] = 0; 47 q.push(s); 48 while(!q.empty()){ 49 int u = q.front(); q.pop(); 50 vis[u] = 0; 51 for(int i = head[u]; ~i; i = nt[i]){ 52 if(w[i] > 0 && d[to[i]] > d[u] + ct[i]){ 53 d[to[i]] = d[u] + ct[i]; 54 pre[to[i]] = u; 55 id[to[i]] = i; 56 if(!vis[to[i]]){ 57 vis[to[i]] = 1; 58 q.push(to[i]); 59 } 60 } 61 } 62 63 } 64 return d[t] < INF; 65 } 66 67 int MaxFlow(){ 68 int Mi = INF; 69 int sum = 0; 70 while(spfa()){ 71 Mi = INF; 72 for(int i = t; i != s; i = pre[i]) 73 Mi = min(Mi, w[id[i]]); 74 for(int i = t; i != s; i = pre[i]){ 75 w[id[i]] -= Mi; 76 w[id[i]^1] += Mi; 77 } 78 sum += d[t]; 79 } 80 return sum; 81 } 82 struct Node{ 83 int l, r, t, op; 84 bool operator < (const Node & x) const { 85 return l < x.l; 86 } 87 }A[N]; 88 int main(){ 89 int T, n, m, k, lost; 90 scanf("%d", &T); 91 while(T--){ 92 scanf("%d%d%d%d", &n, &m, &k, &lost); 93 init(); 94 for(int i = 1; i <= m; i++) 95 scanf("%d%d%d%d", &A[i].l, &A[i].r, &A[i].t, &A[i].op); 96 sort(A+1, A+1+m); 97 s = 0, t = 2 * m+2; 98 for(int i = 1; i <= m; i++){ 99 for(int j = i+1; j <= m; j++){ 100 if(A[i].r <= A[j].l){ 101 add(m + i, j, 1, A[j].t - lost*(A[i].op == A[j].op)); 102 } 103 } 104 } 105 add(s, 2 * m + 1, k, 0); 106 for(int i = 1; i <= m; i++){ 107 add(2 * m + 1, i, 1, A[i].t); 108 add(i, m + i, 1, 0); 109 add(m + i, t, 1, 0); 110 } 111 printf("%d\n", -MaxFlow()); 112 } 113 return 0; 114 }