https://www.luogu.org/problemnew/show/1345
拆点,中间建流量为1的边,跑最小割
#include<cstdio> #include<queue> #include<cstring> #include<algorithm> std::queue<int>que; #define INF 0x7fffffff const int maxn = 10007; inline int read() { int x=0; char c=getchar(); while(c<'0'||c>'9')c=getchar(); while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar(); return x; } int n,m,S,T,src,decc; struct node{ int v,next,flow; }edge[maxn>>1];int head[maxn],num=1,cur[maxn],lev[maxn]; void add_edge(int u,int v,int w) { edge[++num].v=v;edge[num].next=head[u];head[u]=num; edge[num].flow=w; } bool bfs() { while(!que.empty()) que.pop(); std::memset(lev,-1,sizeof lev); memcpy(cur,head,sizeof head); lev[src]=0; que.push(src);int now; while(!que.empty()) { now=que.front();que.pop(); for(int i=head[now];i;i=edge[i].next) { int v=edge[i].v; if(lev[v]==-1&&edge[i].flow>0) { lev[v]=lev[now]+1; if(v==decc)return true; que.push(v); } } } return false; } int dfs(int now,int flow) { if(now==decc)return flow; int rest=0,delta; for(int &i=cur[now];i;i=edge[i].next) { int v=edge[i].v; if(lev[v]==lev[now]+1&&edge[i].flow>0) { delta=dfs(v,std::min(flow-rest,edge[i].flow)); if(delta) { edge[i].flow-=delta; edge[i^1].flow+=delta; rest+=delta;if(rest==flow)break; } } } if(rest==flow)lev[now]=-1;//满流 return rest; } int Dinic() { int ans=0; while(bfs()) ans+=dfs(src,INF); return ans; } int main() { n=read(),m=read(),src=read(),decc=read(); src+=n; for(int i=1;i<=n;++i) { add_edge(i,i+n,1); add_edge(i+n,i,0); } for(int a,b,i=1;i<=m;++i) { a=read(),b=read(); add_edge(a+n,b,INF); add_edge(b,a+n,0); add_edge(b+n,a,INF); add_edge(a,b+n,0); } int ans=Dinic(); printf("%d ",ans); return 0; }