题目错别字很多,且题意不清,但题目还是很好的
经典的最小割模型,结果=收益和-最小割
形如下面的模型
有 n 个物品和两个集合 A,B,如果将一个物品放入 A 集合会得到
a
i
a_i
ai,放入 B 集合会得到
b
i
b_i
bi,还有若干个形如
u
i
u_i
ui,
v
i
v_i
vi,
w
i
w_i
wi 限制条件,表示如果
u
i
u_i
ui 和
v
i
v_i
vi 在一个集合会获得
w
i
w_i
wi。每个物品必须且只能属于一个集合,求最大的收益。
考虑建图,A,B看成S和T,不加后面的点集限制,就只需要S向所有物品连边(权为
a
i
a_i
ai),所有物品向T点连边(权为
b
i
b_i
bi)。
现在考虑后面的约束集,假设在A集合里有影响,因为涉及到多个物品,一一连边很明显是不现实的,这个时候可以建一个虚点,从S向虚点连边(权为
w
i
w_i
wi),从虚点向涉及到的物品连边(权为
i
n
f
inf
inf(无穷大)),权为
i
n
f
inf
inf的原因是不能切断虚点与物品的连接。
根据最大流最小割原理,dinic跑一个最大流即可
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int maxn = 1e5+10;
const int maxm = 1e7+10;
const int inf = 0x7f7f7f7f;
typedef struct Dinic{
typedef struct Edge
{
int u,v,w,nxt;
}Edge;
int head[maxn],hcnt;
int dep[maxn];
int cur[maxn];
Edge e[maxm];
int S,T,N;
void init()
{
memset(head,-1, sizeof head);
hcnt = 0;
S = T = N = 0;
}
void adde(int u,int v,int w)
{
e[hcnt].u = u,e[hcnt].v = v,e[hcnt].w = w;
e[hcnt].nxt = head[u];head[u] = hcnt++;
e[hcnt].u = v,e[hcnt].v = u,e[hcnt].w = 0;
e[hcnt].nxt = head[v];head[v] = hcnt++;
// 01 23 45
//i i^1
}
//BFS
int bfs()
{
rep(i,0,N)
{
dep[i] = inf;
}
queue<int> q;
q.emplace(S);dep[S] = 0;
while(!q.empty())
{
int u = q.front();q.pop();
for(int i = head[u];~i;i = e[i].nxt)
{
int v = e[i].v,w = e[i].w;
if(w > 0 && dep[u] + 1 < dep[v])
{
dep[v] = dep[u] + 1;
if(v == T)
return 1;
q.emplace(v);
}
}
}
return dep[T] != inf;
}
//DFS
int dfs(int s,int mw)
{
if(s == T) return mw;
for(int i = cur[s];~i;i = e[i].nxt)
{
cur[s] = i;
int v = e[i].v,w = e[i].w;
if(w <= 0 || dep[v] != dep[s] + 1)
{
continue;
}
int cw = dfs(v,min(w,mw));
if(cw <= 0) continue;
e[i].w -= cw;
e[i^1].w += cw;
return cw;
}
return 0;
}
ll dinic()
{
ll res = 0;
while(bfs())
{
rep(i,0,N)
{
cur[i] = head[i];
}
while(int d = dfs(S,inf))
{
res += 1ll*d;
}
}
return res;
}
} Dinic;
int n,m,s,t;
int x;
int main(int argc, char const *argv[])
{
ll sum = 0;
scanf("%d",&n);
Dinic din;
din.init();
s = 0, t = n + 1;
din.S = 0,din.T = n + 1;
rep(i,1,n+1) scanf("%d",&x),sum += 1ll * x,din.adde(s,i,x);
rep(i,1,n+1) scanf("%d",&x),sum += 1ll * x,din.adde(i,t,x);
scanf("%d",&m);
din.N = (n + m * 2) * 2;
rep(i,1,m+1)
{
int k,c1,c2;
scanf("%d%d%d",&k,&c1,&c2);
sum += c1 + c2;
din.adde(s,n+i+1,c1);
din.adde(n+m+1+i,t,c2);
while(k--)
{
int s;
scanf("%d",&s);
din.adde(n+i+1,s,inf);
din.adde(s,i+n+m+1,inf);
}
}
ll res = din.dinic();
//cout << res << endl;
printf("%lld\n",sum-res);
return 0;
}