思路:
比较一眼.
长了一个姿势,就是有源汇有上下界网络最小流求法.
首先求可行流,得到满足下界需要的流量,就是从原来的汇流回原来的源的流量(\(C_1\)).
这不见得是最小的.
因此我们删去原来的源和原来的汇之间的边,再求一次从原来的汇到原来的源的最大流(\(C_2\)),也即退掉尽可能多的流量.
由于下界是不会退流的.
显而易见(?).\(C_1-C_2\)就是答案.
据称有时候这样做还会出问题?
大家一起来围观Kanari神犇:详细的~~~~网址如下:
http://blog.csdn.net/huzecong/article/details/8631748
#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
int cnt;
struct MaxflowSolver{
int head[110],next[80010],end[80010],flow[80010],ind;
int d[110],gap[110],stk[110],top,cur[110];
inline void reset(){ind=0,memset(head,-1,sizeof head);}
inline void addedge(int a,int b,int f){int q=ind++;end[q]=b,next[q]=head[a],head[a]=q,flow[q]=f;}
inline void make(int a,int b,int f){addedge(a,b,f),addedge(b,a,0);}
inline void bfs(int T){
static int q[110];int fr=0,ta=0;
memset(d,-1,sizeof d),memset(gap,0,sizeof gap),++gap[d[T]=0],q[ta++]=T;
while(fr^ta){
int i=q[fr++];for(int j=head[i];j!=-1;j=next[j])if(d[end[j]]==-1)++gap[d[end[j]]=d[i]+1],q[ta++]=end[j];
}
}
inline int Maxflow(int S,int T){
int res=0,u=S,Min,ins,i;top=0,bfs(T),memcpy(cur,head,sizeof cur);
while(d[S]<cnt+1){
if(u==T){
for(Min=INF,i=0;i<top;++i)if(flow[stk[i]]<Min)Min=flow[stk[i]],ins=i;
for(res+=Min,i=0;i<top;++i)flow[stk[i]]-=Min,flow[stk[i]^1]+=Min;
u=end[stk[top=ins]^1];
}
if(u!=T&&!gap[d[u]-1])break;
bool find=0;
for(int&j=cur[u];j!=-1;j=next[j])if(flow[j]&&d[u]==d[end[j]]+1){find=1,ins=j;break;}
if(find){stk[top++]=cur[u]=ins,u=end[ins];}
else{
Min=cnt+1;for(int j=head[u];j!=-1;j=next[j])if(flow[j]&&d[end[j]]<Min)Min=d[end[j]],cur[u]=j;
if(!--gap[d[u]])break;++gap[d[u]=Min+1];
if(u!=S)u=end[stk[--top]^1];
}
}return res;
}
}SteinsGate;
int main(){
int n;scanf("%d",&n);
register int i,j;
cnt=n;int SS=0,ST=++cnt,S=++cnt,T=++cnt;
int t,x;SteinsGate.reset();
for(i=1;i<=n;++i){
SteinsGate.make(S,i,INF);
SteinsGate.make(i,T,INF);
scanf("%d",&t);
while(t--)scanf("%d",&x),SteinsGate.make(SS,x,1),SteinsGate.make(i,ST,1),SteinsGate.make(i,x,INF);
}
SteinsGate.make(T,S,INF);
int res;
SteinsGate.Maxflow(SS,ST);
for(j=SteinsGate.head[S];j!=-1;j=SteinsGate.next[j])if(SteinsGate.end[j]==T)res=SteinsGate.flow[j],SteinsGate.flow[j]=SteinsGate.flow[j^1]=0;
printf("%d",res-SteinsGate.Maxflow(T,S));
return 0;
}