传送门
最小割入门题。
注意直接
m
e
m
s
e
t
memset
memset时间会爆炸。
代码:
#include<bits/stdc++.h>
#define N 5005
using namespace std;
const int M=1200*1200*3;
inline int read() {
char ch=getchar(); int i=0;
while(!isdigit(ch))ch=getchar();
while(isdigit(ch)) {i=(i<<1)+(i<<3)+(ch^48); ch=getchar();}
return i;
}
int n,m,ans=0;
struct edge{int v,c,next;};
struct Dinic{
int first[N<<1],cur[N<<1],d[N<<1],cnt,s,t,q[N<<1],hd,tl;
edge e[M];
inline void init(){cnt=1,s=0,t=n+m+1;}
inline void addedge(int u,int v,int c){e[++cnt].v=v,e[cnt].c=c,e[cnt].next=first[u],first[u]=cnt;}
inline void add(int u,int v,int c){addedge(u,v,c),addedge(v,u,0);}
inline bool bfs(){
q[hd=tl=1]=s;
for(int i=0;i<=t;++i)d[i]=-1;
d[s]=0;
while(hd<=tl){
int x=q[hd++];
for(int i=first[x];i;i=e[i].next){
int v=e[i].v;
if(e[i].c&&d[v]==-1)d[v]=d[x]+1,q[++tl]=v;
}
}
return ~d[t];
}
inline int dfs(int x,int f){
if(x==t)return f;
int flow=f;
for(int&i=cur[x];i;i=e[i].next){
int v=e[i].v;
if(!flow)return f;
if(e[i].c&&d[v]==d[x]+1){
int tmp=dfs(v,min(e[i].c,flow));
e[i].c-=tmp,e[i^1].c+=tmp,flow-=tmp;
if(!flow)return f;
}
}
return f-flow;
}
inline int solve(){
int ret=ans,tmp;
while(bfs()){
for(int i=0;i<=t;++i)cur[i]=first[i];
ret-=dfs(s,0x3f3f3f3f);
};
return ret;
}
}dinic;
int main(){
n=read(),m=read(),dinic.init();
for(int i=1,k,val;i<=n;++i){
ans+=(val=read()),dinic.add(dinic.s,i,val),k=read();
while(k--){
int pos=read();
dinic.add(i,pos+n,read());
}
}
for(int i=1;i<=m;++i)dinic.add(i+n,dinic.t,read());
cout<<dinic.solve();
return 0;
}