每条边下界为1,上界INF,然后就是最小费用最大流模板
Code:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=10005,INF=0x3f3f3f3f;
int n,m,s,t,ans=0;
int vis[N<<1],cur[N<<1],tmp[N<<1],head[N<<1],nxt[N<<1],c[N<<1],e[N<<1],tot=1;
int pt[N],in[N],dis[N];
inline void add(int x,int y,int z,int cost){
vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;c[tot]=z;e[tot]=cost;
vis[++tot]=x;nxt[tot]=head[y];head[y]=tot;c[tot]=0;e[tot]=-cost;
}
inline bool spfa(int S,int T){
static queue<int>q;
for(int i=0;i<=T;i++) dis[i]=INF,cur[i]=head[i],pt[i]=0;
dis[S]=0;q.push(S);
while(!q.empty()){
int x=q.front();q.pop();pt[x]=0;
for(int i=head[x];i;i=nxt[i]){
int y=vis[i];
if(!c[i] || dis[y]<=dis[x]+e[i]) continue;
dis[y]=dis[x]+e[i];
if(!pt[y]) pt[y]=1,q.push(y);
}
}
return dis[T]!=INF;
}
int ver[N];
int dfs(int v,int T,int flow,int cost){
ver[v]=1;
if(v==T){ans+=flow*cost;return flow;}
int res=0,k;
for(int &i=cur[v];i;i=nxt[i]){
int y=vis[i];
if(ver[y] || dis[y]!=dis[v]+e[i] || !c[i]) continue;
k=dfs(y,T,min(flow-res,c[i]),cost+e[i]);
if(k){c[i]-=k;c[i^1]+=k;res+=k;if(res==flow) return res;}
}
dis[v]=INF;
return res;
}
inline void dinic(int S,int T){
while(spfa(S,T)){
int t=0;
memcpy(tmp,cur,sizeof(tmp));
do{
memcpy(cur,tmp,sizeof(cur));
memset(ver,0,sizeof(ver));
t=dfs(S,T,INF,0);
}while(t!=0);
}
}
int main(){
n=read();m=n+1;s=m+1;t=s+1;
for(int i=1;i<=n;i++){
int tt=read();in[i]+=tt;
for(int j=1;j<=tt;j++){
int y=read(),z=read();
add(i,y,INF,z);
in[y]--;ans+=z;
}
add(i,m,INF,0);
}
add(m,1,INF,0);
for(int i=1;i<=n;i++){
if(in[i]>0) add(i,t,in[i],0);
if(in[i]<0) add(s,i,-in[i],0);
}
dinic(s,t);
cout<<ans;
return 0;
}