dinic算法

dinic算法是网络流最大流的优化算法之一,每一步对原图进行分层,然后用DFS求增广路。时间复杂度是O(n^2*m)(n是点数,m是边数)

层次图:把原图中的点按照到源的距离分“层”,只保留不同层之间的边的图。

算法流程:

1、根据残量网络计算层次图。

2、在层次图中使用DFS进行增广直到不存在增广路。

3、重复以上步骤直到无法增广。

时间复杂度:

因为在Dinic的执行过程中,每次重新分层,汇点所在的层次是严格递增的,而n个点的层次图最多有n层,所以最多重新分层n次。在同一个层次图中,因为每条增广路都有一个瓶颈,而两次增广的瓶颈不可能相同,所以增广路最多m条。搜索每一条增广路时,前进和回溯都最多n次,所以这两者造成的时间复杂度是O(nm);而沿着同一条边(i,j)不可能枚举两次,因为第一次枚举时要么这条边的容量已经用尽,要么点j到汇不存在通路从而可将其从这一层次图中删除。综上所述,Dinic算法时间复杂度的理论上界是O(n^2*m)。

注意:增广路的长度是递增的。

伪代码,摘自http://www.cnblogs.com/zen_chou/archive/0001/01/01/1525841.html

View Code
 1   初始化,计算剩余图;

 2   while(BFS())    //BFS过程的作用:1,计算层次图;2,当汇点不再层次图内时返回0

 3   {

 4      path.clear();

 5      源点入栈path;   //栈path保存层次图内从原点到终点的可行路径

 6      while(源点的出度不为0)

 7      {

 8         u<-path.top;

 9         if (u!=汇点)        //在层次图内寻找一条从起点到终点的路径

10         {

11           if (u出度大于0)

12             将层次图内与u相连的点v入栈;

13           else

14           {

15             u出栈;      //从path中删除

16             u的level=正无穷;   //从层次图中删除

17           }

18         }

19         else           //对路径增广

20         {

21           在剩余图中沿P增广;

22           令path.top为从起点可到达的最后一个顶点;

23         }

24      }

25   }

dinic代码,演示例子是算法导论P405图。

 

View Code
  1 View Code 

  2   1 #include <iostream>

  3   2 #include <stdio.h>

  4   3 #include <memory.h>

  5   4 #include <list>

  6   5 using namespace std;

  7   6 const int maxnum=21;

  8   7 const int maxdata=(1<<30);

  9   8 int f[maxnum][maxnum];

 10   9 int level[maxnum];

 11  10 bool use[maxnum];

 12  11 int p,e;

 13  12 

 14  13 void Init()

 15  14 {

 16  15     memset(f,0,sizeof(f));

 17  16     scanf("%d%d",&p,&e);

 18  17     int i;

 19  18     int u,v,w;

 20  19     for(i=0;i<e;i++)

 21  20     {

 22  21         scanf("%d%d%d",&u,&v,&w);

 23  22         f[u][v]+=w;

 24  23     }

 25  24 }

 26  25 

 27  26 bool bfs() //Construct the level graph

 28  27 {

 29  28     int i;

 30  29     for(i=1;i<=p;i++)  //start=1,end=p

 31  30     {

 32  31         level[i]=maxdata;

 33  32         use[i]=false;

 34  33     }

 35  34 

 36  35     list<int> l;

 37  36     l.clear();

 38  37     level[1]=0;

 39  38     use[1]=true;

 40  39     l.push_back(1);

 41  40     int t;

 42  41     bool flag=false;

 43  42     while(!l.empty())

 44  43     {

 45  44         t=l.front();

 46  45         l.pop_front();

 47  46         if(t==p)   //因为要求整个图中的层次图,所以最好不要break

 48  47             flag=true;

 49  48         for(i=1;i<=p;i++)

 50  49         {

 51  50             if(f[t][i]!=0 && !use[i])

 52  51             {

 53  52                 level[i]=level[t]+1;

 54  53                 use[i]=true;

 55  54                 l.push_back(i);

 56  55             }

 57  56         }

 58  57     }

 59  58     return flag;

 60  59 }

 61  60 

 62  61 int Outdegree(int u)//compute the out degree of a node in level graph

 63  62 {

 64  63     int i;

 65  64     for(i=1;i<=p;i++)

 66  65         if(f[u][i]!=0 && level[i]==level[u]+1)

 67  66             return i;

 68  67     return 0;

 69  68 }

 70  69 

 71  70 int Dinic()

 72  71 {

 73  72     int sum=0,cf,last;

 74  73     int start=1;

 75  74     int u,v;

 76  75     list<int> s;

 77  76     list<int>::iterator it;

 78  77     while(bfs())

 79  78     {

 80  79         //cout<<"bfs"<<endl;

 81  80         s.clear();

 82  81         s.push_back(start);   //s=1;

 83  82         while(Outdegree(start)>0)

 84  83         {

 85  84             u=s.back();//search the path from s to t in level gragh

 86  85             if(u!=p)

 87  86             {

 88  87                 if((v=Outdegree(u))>0)

 89  88                 {

 90  89                     s.push_back(v);

 91  90                 }

 92  91                 else

 93  92                 {

 94  93                     s.pop_back();

 95  94                     level[u]=maxdata;

 96  95                 }

 97  96             }

 98  97             else //update the residual graph along path

 99  98             {

100  99 

101 100                 cf=maxdata;

102 101                 for(it=s.begin();it!=s.end();it++)

103 102                 {

104 103                     u=*it;

105 104                     //if(u==p)    break;

106 105                     it++;

107 106                     if(it==s.end())

108 107                         break;

109 108                     v=*(it);

110 109                     it--;

111 110                     if(f[u][v]<cf)

112 111                         cf=f[u][v];

113 112                 }

114 113 

115 114                 sum+=cf;

116 115                 last=-1;

117 116                 for(it=s.begin();it!=s.end();it++)

118 117                 {

119 118                     u=*it;

120 119                     //if(u==p)    break;

121 120                     it++;

122 121                     if(it==s.end())

123 122                         break;

124 123                     v=*(it);

125 124                     it--;

126 125                     f[u][v]-=cf;

127 126                     f[v][u]+=cf;

128 127                     if(f[u][v]==0 && last==-1)

129 128                         last=u;//label the last vertex reachable from s

130 129                 }

131 130 

132 131                 while(s.back()!=last)

133 132                     s.pop_back();

134 133             }

135 134         }

136 135     }

137 136     return sum;

138 137 }

139 138 

140 139 int main()

141 140 {

142 141     Init();

143 142     printf("%d\n",Dinic());

144 143     return 0;

145 144 }

146 145 

147 146 

148 147 

149 148 /*

150 149 6 10

151 150 1 2 16

152 151 1 3 13

153 152 2 3 10

154 153 2 4 12

155 154 3 2 4

156 155 3 5 14

157 156 4 3 9

158 157 4 6 20

159 158 5 4 7

160 159 5 6 4

161 160 */

162 161 //for(it=s.begin();it!=s.end();it++)

163 162 //                    cout<<*it<<" ";

164 163 //                cout<<endl;

 

 

你可能感兴趣的:(dinic)