初识网络流(EK and Dinic 模板)

昨天由08的学长讲解了网络流的入门,加上自己之前看过算法导论里面的介绍,有了一点点粗浅的认识!学长给的话里最后一段我感觉很有意义!贴出来看看:

 

今天介绍的只是网络流中最基本一些问题,真正网络流博大精深,是研究生的一本必修课程。北邮的戴牛曾说过一切问题皆网络流,可见它的易用性。本人在有限的ACM生涯中也只是粗略入了门而已,大家练习做这种类型题目切忌百度,网络问题精华就在构图,图出来,什么都是浮云,如果一没思路马上百度,是无法入门,更别谈小成。
 
受益匪浅啊!
 
今天做最大流的问题,就遇到了建图苦难这个难题!认识了Dinic和EK两种算法!算是勉强会用,主要是学长留下的模板好用。
 
贴出来大家分享一下
先是EK的!
View Code
 1 int M,N;
2 int map[NN][NN];
3 int mark[NN];
4 int pre[NN];
5 bool Bfs()
6 {
7 int que[NN];
8 memset(mark,0,sizeof(mark));
9 mark[0]=1;
10 que[0]=0;
11 int cur,i;
12 int j,num=1;
13 for (j=0;j<num;j++)
14 {
15 cur=que[j];
16 for(i=0;i<=N+1;i++) //N+1 的位置代表总得点得个数
17 if(map[cur][i]>0&&!mark[i])
18 {
19 mark[i]=1;
20 pre[i]=cur;
21 if (i==N+1) //走到最后了 返回1
22 returntrue;
23 que[num++]=i;
24 }
25 }
26 returnfalse;
27 }
28 void Edmonds_Karp()
29 {
30 int maxFlow=0;
31 int flow,tmp;
32 while(Bfs())
33 {
34 /*查找最小增流的时候,只查找最短路径上的点*/
35 flow=INF;
36 tmp=N+1; //tmp 等于总得点数
37 while(tmp!=0)
38 {
39 if(map[pre[tmp]][tmp]<flow)
40 flow=map[pre[tmp]][tmp];
41 tmp = pre[tmp];
42 }
43 maxFlow+=flow;
44 tmp=N+1;
45 while(tmp!=0) //0的意思是代表源点
46 {
47 map[pre[tmp]][tmp]-=flow;
48 map[tmp][pre[tmp]]+=flow;
49 tmp=pre[tmp];
50 }
51 }
52 printf("%d\n",maxFlow);
53 }
 
下面是Dinic! 速度相对较快!就是代码复杂
View Code
 1 constint maxn=150000;
2 constint maxm=200000;
3 constint inf=1<<30;
4 struct edge
5 {
6 int from,to,val,next;
7 }map[maxn];
8 int vis[maxn],que[maxn],dist[maxn],len;
9 void init()
10 {
11 len=0;
12 memset(vis,-1,sizeof(vis));
13 }
14 void insert (int from,int to,int val)
15 {
16 map[len].from=from,map[len].to=to,map[len].val=val;
17 map[len].next=vis[from];
18 vis[from]=len++;
19 map[len].from=to,map[len].to=from,map[len].val=0;
20 map[len].next=vis[to];
21 vis[to]=len++;
22 }
23 int Dinic(int n,int s,int t)
24 {
25 int ans=0;
26 while(true)
27 {
28 int head,tail,id,i;
29 head=tail=0;
30 que[tail++]=s;
31 memset(dist,-1,sizeof(dist));
32 dist[s]=0;
33 while(head<tail)
34 {
35 id=vis[que[head++]];
36 while(id!=-1)
37 {
38 if(map[id].val>0&&dist[map[id].to]==-1)
39 {
40 dist[map[id].to]=dist[map[id].from]+1;
41 que[tail++]=map[id].to;
42 if(map[id].to==t)
43 {
44 head=tail;
45 break;
46 }
47 }
48 id=map[id].next;
49 }
50 }
51 if(dist[t]==-1)
52 break;
53 id=s,tail=0;
54 while(true)
55 {
56 if(id==t) //找到一条增广路
57 {
58 int flow=inf,fir;
59 for(i=0;i<tail;i++)
60 if(map[que[i]].val<flow)
61 {
62 fir=i;
63 flow=map[que[i]].val;
64 }
65 for(i=0;i<tail;i++)
66 map[que[i]].val-=flow,map[que[i]^1].val+=flow;
67 ans+=flow;
68 tail=fir;
69 id=map[que[fir]].from;
70 }
71 id=vis[id];
72 while(id!=-1)
73 {
74 if(map[id].val>0&&dist[map[id].from]+1==dist[map[id].to])
75 break;
76 id=map[id].next;
77 }
78 if(id!=-1)
79 {
80 que[tail++]=id;
81 id=map[id].to;
82 }
83 else
84 {
85 if(tail==0)
86 break;
87 dist[map[que[tail-1]].to]=-1;
88 id=map[que[--tail]].from;
89 }
90 }
91 }
92 return ans;
93 }


其中   n为节点数,s为源点,t为汇点,每次使用先初始化!

建图的思考是网络流中的精髓!如果平时不思考!到比赛的时候就是必死了!

切记!

posted @ 2011-08-12 22:05  Lxsec  阅读(2032)  评论(0编辑  收藏  举报