Codeforces 101484 H Eating Pie

来源:互联网 发布:生产线显示屏 网络 编辑:程序博客网 时间:2024/06/05 02:29

题意:给定N 种商品,两个人各有一个购物清单,每个人只购买自己购物清单上出现的商品。现在给定一个商品序列Q,当某个人连续取ii+1 的商品时候,他将获得Pi的糖果奖励。需要值得注意的是,当某个人已经买了Ki的商品,那么其他同种类的商品也必须由这个人购买。问最后获得最大的糖果总数。

思路:考虑最大流,对于任意种类的糖果u,v,如果他们在Q序列中是相连的,那么他们之间的流量就为连续取的糖果奖励。这个图能够保证,如果选择某种糖果,那么所有的糖果之间均有联系。
同时,联系源点和汇点,如果a的购物清单上没有某种类型的商品Ki则建立E(Ki,T),对b的购物清单进行类似的操作。这样的建图能够保证,当a不购买Ki时,b一定能够购买,反之亦然。那么现在,等价于在这个图上找到一个MINCUT,使得该图分成两块,并且剩余边之和最大。

#include<iostream>#include<cstdio>#include<cmath>#include<string>#include<cstring>#include<stack>#include<queue>#include<map>#include<algorithm>#include<bitset>#include<vector>#include <functional>using namespace std;typedef long long ll;typedef pair<ll, ll>pii;#define sp system("pause")const int MAXN = 1100;const int INF = 1e8;int maze[MAXN][MAXN]; int gap[MAXN], dis[MAXN], pre[MAXN], cur[MAXN];int sap(int start, int end, int nodenum) {     memset(cur, 0, sizeof(cur));     memset(dis, 0, sizeof(dis));      memset(gap, 0, sizeof(gap));      int u = pre[start] = start, maxflow = 0, aug = -1;     gap[0] = nodenum;     while (dis[start]<nodenum)      {     loop:              for (int v = cur[u]; v<nodenum; v++)          if (maze[u][v] && dis[u] == dis[v] + 1)           {             if (aug == -1 || aug>maze[u][v])                aug = maze[u][v];                    pre[v] = u;                u = cur[u] = v;                if (v == end)                {                 maxflow += aug;                   for (u = pre[u]; v != start; v = u, u = pre[u])                     {                     maze[u][v] -= aug;                    maze[v][u] += aug;                 }                        aug = -1;             }                goto loop;         }               int mindis = nodenum - 1;         for (int v = 0; v<nodenum; v++)          if (maze[u][v] && mindis>dis[v])         {            cur[u] = v;                mindis = dis[v];        }               if ((--gap[dis[u]]) == 0)            break;              gap[dis[u] = mindis + 1]++;         u = pre[u];     }      return maxflow;}int a[MAXN], b[MAXN];int q[MAXN];int main(){    int k, n, aa, bb;    scanf("%d%d%d%d", &k, &n, &aa, &bb);    memset(a, 0, sizeof a);    memset(maze, 0, sizeof maze);    memset(b, 0, sizeof b);    for (int i = 0; i < aa; i++)    {        int x;        scanf("%d", &x);        a[x] = 1;    }    for (int i = 0; i < bb; i++)    {        int x;        scanf("%d", &x);        b[x] = 1;    }    int all = 0;    for (int i = 0; i < n; i++)        scanf("%d", q + i);    for (int i = 1; i < n; i++)    {        int c;        scanf("%d", &c);        all += c;        maze[q[i - 1]][q[i]] += c;        maze[q[i]][q[i - 1]] += c;    }    for (int i = 1; i <= k; i++)    {        if (b[i] == 0)maze[k + 1][i] = INF;        if (a[i] == 0)maze[i][k + 2] = INF;    }    printf("%d\n", all-sap(k + 1, k + 2, k + 3));    //sp;}
原创粉丝点击