题意:给定
N
种商品,两个人各有一个购物清单,每个人只购买自己购物清单上出现的商品。现在给定一个商品序列
思路:考虑最大流,对于任意种类的糖果
u,v
,如果他们在
Q
序列中是相连的,那么他们之间的流量就为连续取的糖果奖励。这个图能够保证,如果选择某种糖果,那么所有的糖果之间均有联系。
同时,联系源点和汇点,如果a的购物清单上没有某种类型的商品
#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;
}