首先可以用一种类似退流的思想,先建图跑可行流,然后删掉原图的汇点tt~源点ss之间的边,设这条边的流量为x1,再跑tt~ss的最大流x2。答案就是x1-x2。
另一种做法,先不加tt~ss的边跑最大流,然后加边跑最大流x2,答案就为x2。
#include
#include
#include
#include
#define maxn 1005
using namespace std;
struct E{int to,nxt,cap;}b[100005];
int fst[maxn],cur[maxn],tot=1;
void insert(int f,int t,int c)
{
b[++tot]=(E){t,fst[f],c};fst[f]=tot;
b[++tot]=(E){f,fst[t],0};fst[t]=tot;
}
int A[maxn];
void build(int f,int t,int l,int h)
{
insert(f,t,h-l);
A[f]+=l;A[t]-=l;
}
int S,T,mx,inf=1e5;
int rd[maxn];
struct Dinic{
queue<int> Q;
int dis[maxn];
bool bfs()
{
for(int i=1;i<=mx;i++) dis[i]=0;
while(!Q.empty()) Q.pop();
dis[S]=1;Q.push(S);
while(!Q.empty())
{
int u=Q.front();Q.pop();
for(int i=fst[u];i;i=b[i].nxt)
{
int v=b[i].to;
if(b[i].cap&&!dis[v])
{
dis[v]=dis[u]+1;
if(v==T) return true;
Q.push(v);
}
}
}
return false;
}
int dfs(int x,int a)
{
if(x==T||a==0) return a;
int ans=0;
for(int &i=cur[x];i;i=b[i].nxt)
{
int v=b[i].to;
if(b[i].cap&&dis[v]==dis[x]+1)
{
int f=dfs(v,min(a,b[i].cap));
a-=f;ans+=f;
b[i].cap-=f;
b[i^1].cap+=f;
if(a==0) return ans;
}
}
if(a) dis[x]=inf;
return ans;
}
int maxflow()
{
int ans=0;
while(bfs())
{
for(int i=0;i<=mx;i++)
cur[i]=fst[i];
ans+=dfs(S,inf);
}
return ans;
}
}D;
int main()
{
int n,k,x;
scanf("%d",&n);
int ss=n+1,tt=ss+1;T=tt+1;mx=T;
for(int i=1;i<=n;i++)
{
scanf("%d",&k);
if(!k) build(i,tt,0,inf);
while(k--)
{
scanf("%d",&x);rd[x]++;
build(i,x,1,inf);
}
}
for(int i=1;i<=n;i++)
if(!rd[i]) build(ss,i,0,inf);
for(int i=1;i<=tt;i++)
{
if(A[i]>0) insert(i,T,A[i]);
else insert(S,i,-A[i]);
}
insert(tt,ss,inf);
D.maxflow();
int x1=b[tot].cap;
b[tot].cap=b[tot-1].cap=0;
S=tt;T=ss;
int x2=D.maxflow();
cout<return 0;
}
做法二
#include
#include
#include
#include
#define maxn 1005
using namespace std;
struct E{int to,nxt,cap;}b[100005];
int fst[maxn],cur[maxn],tot=1;
void insert(int f,int t,int c)
{
b[++tot]=(E){t,fst[f],c};fst[f]=tot;
b[++tot]=(E){f,fst[t],0};fst[t]=tot;
}
int A[maxn];
void build(int f,int t,int l,int h)
{
insert(f,t,h-l);
A[f]+=l;A[t]-=l;
}
int S,T,mx,inf=1e5;
int rd[maxn];
struct Dinic{
queue<int> Q;
int dis[maxn];
bool bfs()
{
for(int i=1;i<=mx;i++) dis[i]=0;
while(!Q.empty()) Q.pop();
dis[S]=1;Q.push(S);
while(!Q.empty())
{
int u=Q.front();Q.pop();
for(int i=fst[u];i;i=b[i].nxt)
{
int v=b[i].to;
if(b[i].cap&&!dis[v])
{
dis[v]=dis[u]+1;
if(v==T) return true;
Q.push(v);
}
}
}
return false;
}
int dfs(int x,int a)
{
if(x==T||a==0) return a;
int ans=0;
for(int &i=cur[x];i;i=b[i].nxt)
{
int v=b[i].to;
if(b[i].cap&&dis[v]==dis[x]+1)
{
int f=dfs(v,min(a,b[i].cap));
a-=f;ans+=f;
b[i].cap-=f;
b[i^1].cap+=f;
if(a==0) return ans;
}
}
if(a) dis[x]=inf;
return ans;
}
int maxflow()
{
int ans=0;
while(bfs())
{
for(int i=0;i<=mx;i++)
cur[i]=fst[i];
ans+=dfs(S,inf);
}
return ans;
}
}D;
int main()
{
int n,k,x;
scanf("%d",&n);
int ss=n+1,tt=ss+1;T=tt+1;mx=T;
for(int i=1;i<=n;i++)
{
scanf("%d",&k);
if(!k) build(i,tt,0,inf);
while(k--)
{
scanf("%d",&x);rd[x]++;
build(i,x,1,inf);
}
}
for(int i=1;i<=n;i++)
if(!rd[i]) build(ss,i,0,inf);
for(int i=1;i<=tt;i++)
{
if(A[i]>0) insert(i,T,A[i]);
else insert(S,i,-A[i]);
}
int x1=D.maxflow();
insert(tt,ss,inf);
x1=D.maxflow();
cout<return 0;
}