Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1520088
  • 博文数量: 399
  • 博客积分: 8508
  • 博客等级: 中将
  • 技术积分: 5302
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-14 09:28
个人简介

能力强的人善于解决问题,有智慧的人善于绕过问题。 区别很微妙,小心谨慎做后者。

文章分类

全部博文(399)

文章存档

2018年(3)

2017年(1)

2016年(1)

2015年(69)

2013年(14)

2012年(17)

2011年(12)

2010年(189)

2009年(93)

分类: LINUX

2010-02-23 18:51:09

算法:最小割
每个点当做一个任务,从源连一个在A上代价为容量的边,从汇再连一个B上代价为容量的边
如果x,y分开会产生代价,则他们间连一个双向的边,容量为代价
最大流就可以了

有些人,包括曾经的我,都是用Dinic加无数恶心优化过的(我7xxxMs)
曾经考虑找增广路时是否必须多路增广,但是由于听信了某神牛
“多头增广和单头的效果是一样的,我试验过”的指点,所以放弃了。

今天,我试了一下多路增广,发现...3xxxMsAC!

贡献一个29行的Dinic,供大家交流!

int level[Nmax],queue[Nmax];
int MakeLevel(){
int bot,x;
memset(level,0xff,sizeof(level));
level[queue[0]]=0;bot=1;
for (int top=0;top for (edge *p=es[x];p;p=p->next)if (p->c && level[p->e]==-1)
level[queue[bot++]=p->e]=level[x]+1;
}
return level[N-1]!=-1;
}
int FindPath(int u,int alpha){
if (u==N-1)return alpha;
int t,w;
w=0;
for (edge *p=es[u];p && wnext)
if (p->c>0 && level[p->e]==level[u]+1)if (t=FindPath(p->e,Min(p->c,alpha-w))){
p->c-=t;
if (p->opt)p->opt->c+=t;
w+=t;//多路增广优势巨大
}
if (!w)level[u]=-1;//关键的一句话
return w;
}
void Dinic(){
int t;
while (MakeLevel())while (t=FindPath(0,1100000000))res+=t;
}

其中,用到的边用链表存储
struct edge{
int e,//指向的节点
c;//剩余可增广的流量
edge *next,//下一个节点
*opt;//反向边
};
答案保存在全局变量res中,源点使用S,汇点使用N-1
阅读(947) | 评论(0) | 转发(0) |
0

上一篇:SAP

下一篇:SPFA算法

给主人留下些什么吧!~~