Description
有一些任务,需要用到一些机器,可以买可以租,问最大获利.
Solution
网络流.
最大权闭合子图模型.
建图很简单就是S->机器,机器->任务,任务->T.
如果没有租用的话,中间的是INF,不会割掉,加上租用就把容量变成租用的价格即可.
这样求出来的割就是最小损失了,用总数减去即可.
Code
/**************************************************************
Problem: 1391
User: BeiYu
Language: C++
Result: Accepted
Time:3864 ms
Memory:55972 kb
****************************************************************/
#include <bits/stdc++.h>
using namespace std;
#define debug(a) cout<<#a<<"="<<a<<" "
const int INF = 0x3fffffff;
const int N = 3650;
const int M = 3000500;
inline int in(int x=0,char ch=getchar()) { while(ch>'9' || ch<'0') ch=getchar();
while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x; }
int n,m;
int val[N],ned[N],c[N];
struct NetWork {
vector< int > g[N];
struct Edge { int fr,to,fl; }edge[M];
int s,t,cnte,flow,tot;
int cur[N],d[N],p[N];
void AddEdge(int fr,int to,int fl) {
g[fr].push_back(cnte),edge[cnte++]=(Edge){ fr,to,fl };
g[to].push_back(cnte),edge[cnte++]=(Edge){ to,fr,0 };
}
void Build() {
n=in(),m=in();
s=0,t=2*m+n+6;
for(int i=1,x;i<=n;i++) {
for(x=in(),tot+=x,AddEdge(i,t,x),x=in();x--;) {
int idx=in(),cost=in();
AddEdge(n+idx,i,cost);
}
}
for(int i=1;i<=m;i++) {
c[i]=in();
int x=n+i;
AddEdge(s,x,c[i]);
}
// for(int i=1;i<=m;i++) cout<<c1[i]<<" "<<c2[i]<<endl;
}
int BFS() {
queue< int > q;
memset(d,0xff,sizeof(d));
q.push(s),d[s]=1;
for(int x;!q.empty();) {
x=q.front(),q.pop();
for(int i=0,lm=g[x].size(),v;i<lm;i++) if(edge[g[x][i]].fl && d[(v=edge[g[x][i]].to)]==-1) {
d[v]=d[x]+1,q.push(v);
}
}return d[t]!=-1;
}
void Dinic() {
// debug(s),debug(t)<<endl;
for(int u,k;BFS();) {
// cout<<"qwq"<<endl;debug(flow)<<endl;
for(memset(cur,0,sizeof(cur)),u=s,k=0;;) {
if(u==t) {
int mine=0,minf=INF;
for(int i=0;i<k;i++) if(edge[p[i]].fl<minf) minf=edge[p[i]].fl,mine=i;
for(int i=0;i<k;i++) edge[p[i]].fl-=minf,edge[p[i]^1].fl+=minf;
// for(int i=0;i<k;i++) cout<<edge[p[i]].fr<<"-->";cout<<endl;
// debug(minf)<<endl;
k=mine,flow+=minf,u=edge[p[mine]].fr;
}
for(int &i=cur[u],lm=g[u].size(),v;i<lm;i++)
if(edge[g[u][i]].fl && d[(v=edge[g[u][i]].to)]==d[u]+1) break;
if(cur[u]<(int)g[u].size()) {
p[k++]=g[u][cur[u]],u=edge[g[u][cur[u]]].to;
} else {
if(!k) break;
d[u]=-1,u=edge[p[--k]].fr;
}
}
}
}
int Maxflow() {
flow=0,tot=0;
Build();
Dinic();
return tot-flow;
}
}py;
int main() {
cout<<py.Maxflow()<<endl;
return 0;
}