【BZOJ-1391】order 最小割 + 最大全闭合图

时间:2023-03-08 19:27:05

1391: [Ceoi2008]order

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit:
1334  Solved: 405
[Submit][Status][Discuss]

Description

有N个工作,M种机器,每种机器你可以租或者买过来.
每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成。现在给出这些参数,求最大利润

Input

第一行给出 N,M(1<=N<=1200,1<=M<=1200)
下面将有N块数据,每块数据第一行给出完成这个任务能赚到的钱(其在[1,5000])及有多少道工序接下来若干行每行两个数,分别描述完成工序所需要的机器编号及租用它的费用(其在[1,20000])
最后M行,每行给出购买机器的费用(其在[1,20000])

Output

最大利润

Sample Input

2 3
100 2
1 30
2 20
100
2
1 40
3 80
50
80
110

Sample Output

50

HINT

【BZOJ-1391】order      最小割 + 最大全闭合图

Source

Solution

这玩意叫啥来着?    最大权闭合图?   反正是个裸题

于是正常暴力构图,正确性很显然:

假设任务在S一侧,机器在T一侧。

如果任务A在S割且机器B也在S割,那么割掉的是边B-->T,这代表购买机器的代价。

如果任务A在T割且机器B也在T割,那么割掉的是边S-->A,这代表舍弃任务的代价。

如果任务A在S割但机器B在T割,那么割掉的是边A-->B,这代表租用机器的代价。

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;
int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define maxm 3000010
#define maxn 3010
int n,m,tot;
struct EdgeNode{int next,to,cap;}edge[maxm];
int head[maxn],cnt=;
void add(int u,int v,int w) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].cap=w;}
void insert(int u,int v,int w) {add(u,v,w); add(v,u,);}
#define inf 0x7fffffff
int dis[maxn],cur[maxn],S,T;
bool bfs()
{
queue<int>q;
for (int i=S; i<=T; i++) dis[i]=-;
q.push(S); dis[S]=;
while (!q.empty())
{
int now=q.front(); q.pop();
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]==-)
dis[edge[i].to]=dis[now]+,q.push(edge[i].to);
}
return dis[T]!=-;
}
int dfs(int x,int low)
{
if (x==T) return low;
int used=,w;
for (int i=cur[x]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]==dis[x]+)
{
w=dfs(edge[i].to,min(edge[i].cap,low-used));
edge[i].cap-=w; edge[i^].cap+=w; used+=w;
if (edge[i].cap) cur[x]=i; if (low==used) return used;
}
if (!used) dis[x]=-;
return used;
}
int dinic()
{
int tmp=;
while (bfs())
{
for (int i=S; i<=T; i++) cur[i]=head[i];
tmp+=dfs(S,inf);
}
return tmp;
}
int main()
{
n=read(),m=read();
S=,T=n+m+;
for (int x,y,i=; i<=n; i++)
{
x=read(),y=read(); tot+=x;
insert(S,i,x);
for (int z,c,j=; j<=y; j++)
z=read(),c=read(),insert(i,z+n,c);
}
for (int x,i=; i<=m; i++) x=read(),insert(i+n,T,x);
printf("%d\n",tot-dinic());
return ;
}