最小费用最大流-SPFA-多路增广
发布日期:2021-06-29 06:00:13
浏览次数:2
分类:技术文章
本文共 2857 字,大约阅读时间需要 9 分钟。
背景
在最近的模拟赛当中,我碰到了一题二分图最大权匹配的题,建图比较简单,因为是IOI赛制,所以可以爆OJ,然后呢,打了一发普通的spfa费用流,跑的很慢诶,只拿了70分,都有人AC了呢。那天的讲题,好像说写KM(二分图最大权完美匹配的一种算法)就能过,但是呢,新的东西学还是需要一段时间的,但要订正的话,emm,还是学一学优化的spfa费用流吧,即多路增广一下,事实证明这是能过的。
算法介绍
多路增广非常类似于dinic,然后我不会啊,然后就向高届的大佬请教,大致的算法过程如下
对整一幅图做一遍spfa(这个和一般spfa费用流相似),若汇点的距离为INF(意味着不能增广),那么退出,否则做如下操作 每一次都用dfs进行一次增广,若某一次增广的流量为0,那么spfa一遍重新做 dfs是多路增广与一般增广的最大不同之处,每到一个点u,它要去扩展所有的点v满足dis[u]+vau(边权)==dis[v] 当然,需要使用当前弧优化才能保证复杂度应用
相对于一般的spfa费用流,多路增广尤其适用于边流量特别小的图(这些图一次spfa如果只扩展一条边那么效率将会变得很低下)
实现代码
#include#include #include #include #include namespace fast_IO{ const int IN_LEN=10000000,OUT_LEN=10000000; char ibuf[IN_LEN],obuf[OUT_LEN],*ih=ibuf+IN_LEN,*oh=obuf; char *lastin=ibuf+IN_LEN; const char *lastout=ibuf+OUT_LEN-1; inline char getchar_() { if(ih==lastin)lastin=ibuf+fread(ibuf,1,IN_LEN,stdin),ih=ibuf; return (*ih++); } inline void putchar_(const char x) { if(ih==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf; *oh++=x; } inline void flush(){ fwrite(obuf, 1, oh - obuf, stdout);}}using namespace fast_IO;//#define getchar() getchar_()//#define putchar(x) putchar_((x))typedef long long LL;#define rg registertemplate inline T max(const T a,const T b){ return a>b?a:b;}template inline T min(const T a,const T b){ return a inline T abs(const T a){ return a>0?a:-a;}template inline void swap(T&a,T&b){ T c=a;a=b;b=c;}template inline T gcd(const T a,const T b){ if(a%b==0)return b;return gcd(b,a%b);}template inline T square(const T x){ return x*x;};template inline void read(T&x){ char cu=getchar();x=0;bool fla=0; while(!isdigit(cu)){ if(cu=='-')fla=1;cu=getchar();} while(isdigit(cu))x=x*10+cu-'0',cu=getchar(); if(fla)x=-x; }template void printe(const T x){ if(x>=10)printe(x/10); putchar(x%10+'0');}template inline void print(const T x){ if(x<0)putchar('-'),printe(-x); else printe(x);}const int maxn=5002,maxm=100003;int N,M,S,T,maxflow,mincost;int head[maxn],cur[maxn],nxt[maxm],tow[maxm],vau[maxm],cost[maxm],tmp=1;inline void addb(const int u,const int v,const int w,const int f){ tmp++; nxt[tmp]=head[u]; head[u]=tmp; tow[tmp]=v; vau[tmp]=w; cost[tmp]=f;}int dis[maxn],fr[maxn];int Q[maxn],l,r;bool Hash[maxn];inline int spfa(){ memset(dis,0x7f,sizeof(dis)); dis[S]=0; Hash[S]=1; l=r=0; Q[++r]=S; while(l!=r) { l++;if(l==maxn)l=1; const int u=Q[l]; for(rg int i=head[u];i;i=nxt[i]) { const int v=tow[i]; if(vau[i]&&dis[u]+cost[i] =0x7f7f7f3e)return; } }}int main(){ read(N),read(M),read(S),read(T); for(rg int i=1;i<=M;i++) { int u,v,w,f;read(u),read(v),read(w),read(f); addb(u,v,w,f),addb(v,u,0,-f); } flow(); print(maxflow),putchar(' '),print(mincost); return flush(),0;}
注意事项
使用多路增广网络流使用于一些有性质的图会有很好的效果,但如果只是一般的图的话那么效果就不是那么明显啦(可能是我写的常数比较大吧),所以呢,学多路增广之后,对于普通spfa费用流的熟练掌握还是挺重要的
转载地址:https://blog.csdn.net/zhouyuheng2003/article/details/79133619 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月25日 04时56分16秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
树莓派摄像头及视频
2019-04-29
树莓派杂项
2019-04-29
SVG操作
2019-04-29
阿里云ECS使用
2019-04-29
VC6 C/CPP操作ORACLE数据库 clilib方案
2019-04-29
single修改版
2019-04-29
IIS 多站点HTTPS加密及自动http跳转到https
2019-04-29
NGINX重启HTTPS站点要Enter PEM pass phrase输入密码
2019-04-29
树莓派GPIO
2019-04-29
Android 热敏打印机打印二维码
2019-04-29
用vcgencmd获取树莓派硬件状态数据
2019-04-29
IIS 多域名多张证书配置
2019-04-29
树莓派LINUX 截屏
2019-04-29
树莓派Raspberry Pi的嵌入式QT平台
2019-04-29
apache https
2019-04-29
Debian Jessie安装支持HTML5音视频的Chromium浏览器听百度音乐
2019-04-29
nanopi2 启动信息
2019-04-29
POS打印机驱动大全
2019-04-29
phpstudy https
2019-04-29
centos apache 最新版HTTPS配置
2019-04-29