若选择任务,必须选择对应的机器。最大权闭合图模型。。
然后我发现我对网络流的理解很不到位,稍微一变形我就跪了。
有必要再回去研究一下QAQ。
题解:
注意看最大权闭合子图中间连的无穷容量的边,这条边 < u , v > 限制了u选取的时候,v必须选取。
那么这道题的关系就是“可以选u的时候可以不选v,但是要付出一定的代价”。
那么把这条边的容量改为这个代价即可。
这样为什么是对的呢?我们来看割与实际方案的对应关系:
假设任务在S一侧,机器在T一侧。
如果任务a在S割且机器b也在S割,那么割掉的是边 < b , T > ,这代表购买机器的代价。
如果任务a在T割且机器b也在T割,那么割掉的是边 < S , a > ,这代表舍弃任务的代价。
如果任务a在S割但机器b在T割,那么割掉的是边 < a , b > , 这代表租用机器的代价。
注意加当前弧优化,不加我是BZOJ倒一。。卡着边过。。
#include<iostream>
#include<cstdio>
#include<cstring>
#define inf 1000000007
using namespace std;
int n,m,cnt=1,S,T,ans;
int head[2505],q[2505],dis[2505],cur[2505];
int next[3000005],list[3000005],key[3000005];
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
inline void insert(int x,int y,int z)
{
next[++cnt]=head[x];
head[x]=cnt;
list[cnt]=y;
key[cnt]=z;
}
inline bool BFS()
{
memset(dis,-1,sizeof(dis));
dis[S]=1; q[1]=S;
int t=0,w=1,x;
while (t<w)
{
x=q[++t];
for (int i=head[x];i;i=next[i])
if (key[i]&&dis[list[i]]==-1)
dis[list[i]]=dis[x]+1,q[++w]=list[i];
}
return dis[T]!=-1;
}
int find(int x,int flow)
{
if (x==T) return flow;
int w,used=0;
for (int i=cur[x];i;i=next[i])
if (key[i]&&dis[list[i]]==dis[x]+1)
{
w=find(list[i],min(flow-used,key[i]));
key[i]-=w; key[i^1]+=w; used+=w;
if (key[i]) cur[x]=i;
if (used==flow) return flow;
}
if (!used) dis[x]=-1;
return used;
}
int main()
{
n=read(); m=read(); T=n+m+1;
for (int i=1;i<=n;i++)
{
int x=read(),s=read();
insert(S,i,x); insert(i,S,0);
ans+=x;
while (s--)
{
int x=read(),y=read();
insert(i,x+n,y),insert(x+n,i,0);
}
}
for (int i=1;i<=m;i++)
{
int x=read();
insert(i+n,T,x); insert(T,i+n,0);
}
while (BFS())
{
for (int i=0;i<=T;i++) cur[i]=head[i];
ans-=find(S,inf);
}
cout << ans;
return 0;
}