费用流&网络流模版
费用流模版:
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 6 const int Maxm=100000;//最大边数 7 const int Maxn=1000;//最大点数 8 struct Edge{ 9 Edge(){}; 10 Edge(int a,int b,int c,int d,int e){ 11 u=a; 12 v=b; 13 f=c; 14 w=d; 15 nxt=e; 16 } 17 int u,v,f,w,nxt;//U当前点 V来自点 F最大流量 W费用 NXT下一个点 18 }; 19 int cnt=1;//边计数 20 int inf=2147483647;//无限大 21 int g[Maxn+10];//点的边集的开始序号 22 Edge e[Maxm+10];//边集 23 int dist[Maxn+10];//费用 24 int src,sink;//源点与汇点 25 queue<int> que;//宽搜队列 26 bool inque[Maxn+10];//宽搜判断标志 27 int from[Maxn+10];//来源->用于计算费用 28 int ans=0;//存储最小费用 29 30 inline int remin(int a,int b){ 31 return a<b?a:b; 32 } 33 34 inline void insert(int u,int v,int f,int w){ 35 cnt++; 36 e[cnt]=Edge(u,v,f,w,g[u]); 37 g[u]=cnt;//增加一个边 38 } 39 40 inline void addEdge(int u,int v,int f,int w){ 41 insert(u,v,f,w);//插入正边 42 insert(v,u,0,-w);//插入反边 43 } 44 45 inline bool spfa(){ 46 while (!que.empty()) que.pop();//清空队列 47 for (int i=0;i<=sink;i++) dist[i]=inf;//清最大值 48 que.push(src); 49 inque[src]=true; 50 dist[src]=0;//加入源点 51 //标准SPFA计算最短路 流量作为通行标准,费用作为路径长度 52 while(!que.empty()){ 53 int now=que.front(); 54 que.pop(); 55 for (int i=g[now];i;i=e[i].nxt){ 56 if (e[i].f!=0 && dist[e[i].v]>dist[now]+e[i].w){ 57 dist[e[i].v]=dist[now]+e[i].w; 58 from[e[i].v]=i; 59 if (inque[e[i].v]==false){ 60 inque[e[i].v]=true; 61 que.push(e[i].v); 62 } 63 } 64 } 65 inque[now]=false; 66 } 67 if (dist[sink]==inf) return false;//无法在增广 68 return true; 69 } 70 71 inline void calcAns(){ 72 int minflow=inf; 73 for (int i=from[sink];i;i=from[e[i].u]) minflow=remin(minflow,e[i].f);//寻找整条路经的流量 74 for (int i=from[sink];i;i=from[e[i].u]) { 75 e[i].f-=minflow;//正边减流量 76 e[i^1].f+=minflow;//反边加流量 77 ans+=e[i].w*minflow;//计算费用 78 } 79 } 80 81 inline void minCostFlow(){ 82 while(spfa())calcAns(); 83 } 84 85 int main(){ 86 minCostFlow(); 87 return 0; 88 }
网络流模版:
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 6 const int Maxm=100000;//最大边数 7 const int Maxn=1000;//最大点数 8 struct Edge{ 9 Edge(){}; 10 Edge(int a,int b,int c,int d,int e){ 11 u=a; 12 v=b; 13 f=c; 14 w=d; 15 nxt=e; 16 } 17 int u,v,f,w,nxt;//U当前点 V来自点 F最大流量 W费用 NXT下一个点 18 }; 19 int cnt=1;//边计数 20 int inf=2147483647;//无限大 21 int g[Maxn+10];//点的边集的开始序号 22 Edge e[Maxm+10];//边集 23 int dist[Maxn+10];//费用 24 int src,sink;//源点与汇点 25 queue<int> que;//宽搜队列 26 bool inque[Maxn+10];//宽搜判断标志 27 int from[Maxn+10];//来源->用于计算费用 28 int ans=0;//存储最小费用 29 30 inline int remin(int a,int b){ 31 return a<b?a:b; 32 } 33 34 inline void insert(int u,int v,int f,int w){ 35 cnt++; 36 e[cnt]=Edge(u,v,f,w,g[u]); 37 g[u]=cnt;//增加一个边 38 } 39 40 inline void addEdge(int u,int v,int f,int w){ 41 insert(u,v,f,w);//插入正边 42 insert(v,u,0,-w);//插入反边 43 } 44 45 inline bool spfa(){ 46 while (!que.empty()) que.pop();//清空队列 47 for (int i=0;i<=sink;i++) dist[i]=inf;//清最大值 48 que.push(src); 49 inque[src]=true; 50 dist[src]=0;//加入源点 51 //标准SPFA计算最短路 流量作为通行标准,费用作为路径长度 52 while(!que.empty()){ 53 int now=que.front(); 54 que.pop(); 55 for (int i=g[now];i;i=e[i].nxt){ 56 if (e[i].f!=0 && dist[e[i].v]>dist[now]+e[i].w){ 57 dist[e[i].v]=dist[now]+e[i].w; 58 from[e[i].v]=i; 59 if (inque[e[i].v]==false){ 60 inque[e[i].v]=true; 61 que.push(e[i].v); 62 } 63 } 64 } 65 inque[now]=false; 66 } 67 if (dist[sink]==inf) return false;//无法在增广 68 return true; 69 } 70 71 inline void calcAns(){ 72 int minflow=inf; 73 for (int i=from[sink];i;i=from[e[i].u]) minflow=remin(minflow,e[i].f);//寻找整条路经的流量 74 for (int i=from[sink];i;i=from[e[i].u]) { 75 e[i].f-=minflow;//正边减流量 76 e[i^1].f+=minflow;//反边加流量 77 ans+=e[i].w*minflow;//计算费用 78 } 79 } 80 81 inline void minCostFlow(){ 82 while(spfa())calcAns(); 83 } 84 85 int main(){ 86 minCostFlow(); 87 return 0; 88 }