标签:
这道题最麻烦的就是建图,详细的建图过程在 这里
建完图就直接用dinic算法求最大流就行了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#define N 1010
const int INF = 0x3f3f3f3f;
using namespace std;
int cap[N][N], level[N], n, m, q[N], house[N], last[N];
bool bfs(int st, int en){
int rear = 0, front = 0;
memset(level, 0, sizeof(level));
level[st] = 1;
q[front++] = st;
while(rear < front){
int u = q[rear++];
if (u == en) return true;
for (int v = 0; v <= m+n+1; v++){
if (cap[u][v] && level[v] == 0){
level[v] = level[u] + 1;
q[front++] = v;
}
}
}
return false;
}
int dfs(int u, int maxf, int en){
if (u == en){
return maxf;
}
int ret = 0;
for (int v = 0; v <= m+n+1; v++){
if (cap[u][v] && level[v] == level[u]+1){
int f = dfs(v, min(maxf-ret, cap[u][v]), en);
ret += f;
cap[u][v] -= f;
cap[v][u] += f;
if (ret == maxf) return ret;
}
}
return ret;
}
int dinic(int st, int en){
int ans = 0;
while(bfs(st, en)){
ans += dfs(st, INF, en);
}
return ans;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1.txt", "r", stdin);
#endif
int i, j, k, x, y, v;
while(~scanf("%d%d", &m, &n)){
memset(cap, 0, sizeof(cap));
memset(last, 0, sizeof(last));
for (i = 1; i <= m; i++){
scanf("%d", &house[i]);
}
for (i = 1; i <= n; i++){
scanf("%d", &j);
while(j--){
scanf("%d", &v);
if (!last[v]){
last[v] = i;
cap[0][i] += house[v];
}else{
cap[last[v]][i] = INF;
}
}
scanf("%d", &v);
cap[i][n+1] += v;
}
printf("%d\n", dinic(0, n+1));
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/qq_21120027/article/details/51344391