HDU-6437 Videos

HDU-6437

题意:一天有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。

由于是需要最大的愉悦值, 我们把花费取反, 然后跑费用流。 最后把答案取反。

代码:

  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
", -MaxFlow());
112     }
113     return 0;
114 }
View Code
原文地址:https://www.cnblogs.com/MingSD/p/9525169.html