#【网络流24题】最小路径覆盖问题(最大流) ##题面 Cogs ##题解 考虑图的最大匹配 每进行一次成功的匹配 至关于把两条路径合并在一块儿 也就是说,每次多了一组匹配,至关于最终的最小路径覆盖的答案减一 因此咱们有:最小路径覆盖=总点数-最大流(最大匹配数) 因此,这题能够直接作匈牙利算法(算二分图最大匹配,求路径方便一些)php
若是是网络流求解的话 首先拆点 而后连边 而后就是输出路径之类的东西ios
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; #define MAX 5000 #define MAXL 500000 #define INF 1000000000 inline int read() { int x=0,t=1;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } struct Line { int v,next,w; }e[MAXL]; int h[MAX],cnt; int ans,S,T,n,m; inline void Add(int u,int v,int w) { e[cnt]=(Line){v,h[u],w}; h[u]=cnt++; e[cnt]=(Line){u,h[v],0}; h[v]=cnt++; } int level[MAX]; int cur[MAX]; bool vis[MAX]; bool BFS() { memset(level,0,sizeof(level)); level[S]=1; queue<int> Q; Q.push(S); while(!Q.empty()) { int u=Q.front();Q.pop(); for(int i=h[u];i!=-1;i=e[i].next) { int v=e[i].v; if(e[i].w&&!level[v]) level[v]=level[u]+1,Q.push(v); } } return level[T]; } int DFS(int u,int flow) { if(flow==0||u==T)return flow; int ret=0; for(int &i=cur[u];i!=-1;i=e[i].next) { int v=e[i].v; if(e[i].w&&level[v]==level[u]+1) { int dd=DFS(v,min(flow,e[i].w)); flow-=dd;ret+=dd; e[i].w-=dd;e[i^1].w+=dd; } } return ret; } int Dinic() { int ret=0; while(BFS()) { for(int i=S;i<=T;++i)cur[i]=h[i]; ret+=DFS(S,INF); } return ret; } int main() { freopen("path3.in","r",stdin); freopen("path3.out","w",stdout); memset(h,-1,sizeof(h)); n=read();m=read(); S=0;T=n+n+1; for(int i=1;i<=n;++i)Add(S,i,1); for(int i=1;i<=n;++i)Add(i+n,T,1); for(int i=1;i<=m;++i) { int u=read(),v=read(); Add(u,v+n,1); } int ff=Dinic(); for(int i=1;i<=n;++i) if(!vis[i]) { int now=i; do { vis[now]=true; printf("%d ",now); for(int j=h[now];j!=-1;j=e[j].next) { int v=e[j].v; if(v<=n)continue; if(!e[j].w){now=v-n;break;} } }while(!vis[now]); puts(""); } printf("%d\n",n-ff); return 0; }