【题意】

有n个有偿工作选做,m个机器,完成一个工作需要若干个工序,完成每个工序需要一个机器,对于一个机器,在不同的工序有不同的租费,但买下来的费用只有一个。问最大获益。

【思路】

对于工作和机器建点,由S向每一个工作连边(S,u,a)a为完成工作的奖励,由一个工作向所需机器连边(u,v,b)b为租用机器费用,由每个机器向T连边(v,T,c)c为购买机器的费用。

  求最小割,构图提供的选择有:不做该工作,租用一个工序需要的机器,购买一个机器满足所有需要。最小割保证ST不相连,即保证给所有工作分配了一种方案:完成所有工序或不做该工作,且该方案花费最少,最小割即为最小亏损。

【代码】

 #include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; typedef long long ll;
const int N = 4e3+;
const int inf = 1e9; ll read() {
char c=getchar();
ll f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} struct Edge {
int u,v,cap,flow;
};
struct Dinic {
int n,m,s,t;
int d[N],cur[N],vis[N];
vector<int> g[N];
vector<Edge> es;
queue<int> q;
void init(int n) {
this->n=n;
es.clear();
FOR(i,,n) g[i].clear();
}
void AddEdge(int u,int v,int w) {
es.push_back((Edge){u,v,w,});
es.push_back((Edge){v,u,,});
m=es.size();
g[u].push_back(m-);
g[v].push_back(m-);
}
int bfs() {
memset(vis,,sizeof(vis));
q.push(s); d[s]=; vis[s]=;
while(!q.empty()) {
int u=q.front(); q.pop();
FOR(i,,(int)g[u].size()-) {
Edge& e=es[g[u][i]];
int v=e.v;
if(!vis[v]&&e.cap>e.flow) {
vis[v]=;
d[v]=d[u]+;
q.push(v);
}
}
}
return vis[t];
}
int dfs(int u,int a) {
if(u==t||!a) return a;
int flow=,f;
for(int& i=cur[u];i<g[u].size();i++) {
Edge& e=es[g[u][i]];
int v=e.v;
if(d[v]==d[u]+&&(f=dfs(v,min(a,e.cap-e.flow)))>) {
e.flow+=f;
es[g[u][i]^].flow-=f;
flow+=f; a-=f;
if(!a) break;
}
}
return flow;
}
int MaxFlow(int s,int t) {
this->s=s,this->t=t;
int flow=;
while(bfs()) {
memset(cur,,sizeof(cur));
flow+=dfs(s,inf);
}
return flow;
}
} dc; int n,m,S,T; int main()
{
n=read(),m=read();
dc.init(n+m+);
int S=,T=n+m+;
int ans=;
FOR(i,,n) {
int a=read(),b=read();
ans+=a;
dc.AddEdge(S,i,a);
FOR(j,,b) {
int x=read(),y=read();
dc.AddEdge(i,x+n,y);
}
}
FOR(i,,m) {
int x=read();
dc.AddEdge(n+i,T,x);
}
printf("%d",ans-dc.MaxFlow(S,T));
return ;
}

最新文章

  1. linux下vi命令大全
  2. (Array,位操作)137. Single Number II
  3. pre标签避免一行过长打破格局
  4. Linux Apache prefork和worker的原理详解
  5. LeetCode() Search a 2D MatrixII
  6. ActiveMQ(5.10.0) - Message Redelivery and DLQ Handling
  7. OC10_文件练习
  8. SQL Server调优系列基础篇 - 索引运算总结
  9. 静态代理VS动态代理
  10. STM32F072B-DISCO 深入研究 中断系统
  11. 【HDOJ】4983 Goffi and GCD
  12. 使用react-native做一个简单的应用-05 navigator的使用
  13. Jmeter之解决烦人的中文乱码问题
  14. spring+jidi读取property的配置文件
  15. day20 二十、加密模块、操作配置文件、操作shell命令、xml模块
  16. Gym - 101201E:Enclosure (点到凸包的切线)
  17. Linux内核如何装载和启动一个可执行程序(转)
  18. iOS.Objective-C.Dependency.Graphing-v0.1
  19. 通过pycharm使用git
  20. 推荐一款基于Angular实现的企业级中后台前端/设计解决方案脚手架

热门文章

  1. Sina App Engine(SAE)入门教程(1)
  2. 开发版本控制git
  3. Delphi 中的 procedure of object (类方法存在一个隐藏参数self),简单深刻 good
  4. sql中exists,not exists的用法
  5. (转)Spring的编程式事务例子
  6. linux下操作PostgreSQL的常用命令
  7. Java连接MySQL数据库及简单操作代码
  8. Codeforces Round #206 (Div. 1)B(记忆化)
  9. ie下jquery ajax 80020101错误的解决方法
  10. 1085: [SCOI2005]骑士精神