[lnsyoj2610/luoguP2762] 太空飞行计划问题
题意
有 种实验, 种器材,第 种实验需要器材集合为 ,完成第 种实验可以获得 元,使用第 种器材需要 元,求最大利润。
sol
将实验作为左部点,器材作为右部点,根据依赖关系连边,左部连边奖金,右部连边成本。
记选择做的实验收益和为 ,选择不做的实验收益和为 ,选择的器材成本为 ,不选择的器材成本为 ,则最小割为 ,那么使用总收益-最小割即为 。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int N = 105, M = 6005, INF = 0x3f3f3f3f;
int h[N], e[M], cap[M], ne[M], idx;
int d[N], cur[N];
int n, S, T;
int nn, m;
int exprc[N], expr[N][N], cost[N];
char s[205];
bool st[N];
void add(int a, int b, int c){
e[idx] = b, cap[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
e[idx] = a, cap[idx] = 0, ne[idx] = h[b], h[b] = idx ++ ;
}
void build(){
memset(h, -1, sizeof h);
n = nn + m + 2;
S = n - 1, T = n;
for (int i = 1; i <= nn; i ++ ) add(S, i, exprc[i]);
for (int i = 1; i <= m; i ++ ) add(nn + i, T, cost[i]);
for (int i = 1; i <= nn; i ++ )
for (int j = 1; j <= expr[i][0]; j ++ )
add(i, nn + expr[i][j], INF);
}
void print() {
for (int i = 1; i <= nn; i ++ ) if (~d[i]) {
printf("%d ", i);
for (int j = 1; j <= expr[i][0]; j ++ )
st[expr[i][j]] = true;
}
puts("");
for (int i = 1; i <= m; i ++ )
if (st[i])
printf("%d ", i);
puts("");
}
bool bfs(){
queue<int> q;
memset(d, -1, sizeof d);
d[S] = 0, q.push(S), cur[S] = h[S];
while (!q.empty()) {
int t = q.front();
q.pop();
for (int i = h[t]; ~i; i = ne[i]){
int j = e[i];
if (d[j] == -1 && cap[i]) {
d[j] = d[t] + 1;
cur[j] = h[j];
if (j == T) return true;;
q.push(j);
}
}
}
return false;
}
int find(int u, int limit){
if (u == T) return limit;
int flow = 0;
for (int i = cur[u]; ~i && flow < limit; i = ne[i]){
int j = e[i];
cur[u] = i;
if (d[j] == d[u] + 1 && cap[i]){
int t = find(j, min(cap[i], limit - flow));
if (!t) d[t] = -1;
cap[i] -= t; cap[i ^ 1] += t; flow += t;
}
}
return flow;
}
int dinic(){
int r = 0, flow;
while (bfs()) while (flow = find(S, INF)) r += flow;
return r;
}
int main(){
scanf("%d%d", &nn, &m);
int sum = 0;
for (int i = 1; i <= nn; i ++ ) {
scanf("%d", &exprc[i]);
sum += exprc[i];
memset(s, 0, sizeof s);
cin.getline(s, 200);
int ulen = 0, t;
while (sscanf(s + ulen, "%d", &t) == 1) {
expr[i][ ++ expr[i][0]] = t;
if (!t) ulen ++ ;
else
while (t) t /= 10, ulen ++ ;
ulen ++ ;
}
}
for (int i = 1; i <= m; i ++ ) scanf("%d", &cost[i]);
build();
int t = dinic();
print();
printf("%d\n", sum - t);
}
标签:
图论
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现