Dinic算法 (poj3281 Dining)

关于Dinic算法 (Dinic's algorithm, Dinitz blocking flow algorithm) 步骤: 
   1 .初始化流量,计算出剩余图
  
2 .根据剩余图计算层次图(BFS),若汇点不在层次图内,则算法结束
  
3 .在层次图内用一次DFS增广
  
4 .转步骤2

层次图指用一次BFS计算每个节点到源点的距离(level),源点的level为0。Dinic精髓在第三步,在层次图内用一次DFS增广。在程序实现的时候,层次图并不需要被构造出来,只需要对每个顶点标记一个层次,寻找路径的时候,判断边是否满足 level[u]+1==level[v]这一约束即可。

下面给出Dinic的伪码:
  初始化,计算剩余图;
  
while (BFS())     // BFS过程的作用:1,计算层次图;2,当汇点不再层次图内时返回0
  {
     path.clear();
     源点入栈path;    // 栈path保存层次图内从原点到终点的可行路径
      while (源点的出度不为0)
     {
        u
<- path.top;
        
if  (u != 汇点)         // 在层次图内寻找一条从起点到终点的路径
        {
          
if  (u出度大于0)
            将层次图内与u相连的点v入栈;
          
else
          {
            u出栈;      
// 从path中删除
            u的level = 正无穷;    // 从层次图中删除
          }
        }
        
else             // 对路径增广
        {
          在剩余图中沿P增广;
          令path.top为从起点可到达的最后一个顶点;
        }
     }
  }

poj3281这题主要是构图的问题:把一头牛拆成两份,一份与对应Drink相连,一份与对应Food相连,两份相同牛之间连一条路径。再添加一个起点和一个终点,起点与每份Drink相连,每份Food与终点相连。所有路径的权值都为1,且方向一致指向从起点到终点。

poj3281的代码, Time:63MS ExpandedBlockStart.gif
ContractedBlock.gif ExpandedBlockStart.gif Code
  1 //AC T:63MS
  2 #include <iostream>
  3 #include <list>
  4 #define GSIZE 402
  5 #define INF 10000000
  6 using namespace std;
  7 int N, F, D, src, sink;
  8 int resflow[GSIZE][GSIZE], color[GSIZE], level[GSIZE];
  9 int OutDegree(int x)//compute the out degree of a node in level graph
 10 {
 11     int i;
 12     for (i=0;i<=sink;i++){
 13         if (resflow[x][i]!=0 && level[x]+1==level[i])
 14             return i;
 15     }
 16     return 0;
 17 }
 18 
 19 int BFS()//Construct the level graph
 20 {
 21     int i, u, v, flag;
 22     list<int> l;//queue
 23     flag=0;
 24     for (i=1;i<=sink;i++){//necessary?
 25         level[i]=INF;
 26         color[i]=0;
 27     }
 28     color[src]=1;
 29     l.push_back(src);
 30     while(!l.empty()){
 31         u=l.front();
 32         l.pop_front();
 33         for (v=0;v<=sink;v++){
 34             if (resflow[u][v]!=0 && color[v]==0){
 35                 color[v]=1;
 36                 level[v]=level[u]+1;
 37                 l.push_back(v);
 38             }
 39         }
 40         if (u==sink)
 41             flag=1;
 42         color[u]=2;
 43     }
 44     return flag;
 45 }
 46 
 47 int Dinic()
 48 {
 49     int maxflow, u, v, capflow, last;
 50     list<int> path;//stack
 51     list<int>::iterator it;
 52     maxflow=0;
 53     while(BFS()){
 54         path.clear();
 55         path.push_back(src);
 56         while (OutDegree(src)>0){
 57             u=path.back();
 58             //search the path from s to t in level graph
 59             if (u!=sink){
 60                 if ((v=OutDegree(u))!=0)
 61                     path.push_back(v);
 62                 else{
 63                     path.pop_back();
 64                     level[u]=INF;
 65                 }
 66             }
 67             //update the residual graph along path
 68             else{
 69                 capflow=INF;
 70                 for (it=path.begin();it!=path.end();it++){
 71                     u=*it;
 72                     if ((++it)==path.end())
 73                         break;
 74                     v=*it;
 75                     if (resflow[u][v]<capflow)
 76                         capflow=resflow[u][v];
 77                     --it;
 78                 }
 79                 last=-1;
 80                 maxflow+=capflow;
 81                 for (it=path.begin();it!=path.end();it++){
 82                     u=*it;
 83                     if ((++it)==path.end())
 84                         break;
 85                     v=*it;
 86                     resflow[u][v]-=capflow;
 87                     resflow[v][u]+=capflow;
 88                     if (resflow[u][v]==0 && last==-1)//label the last vertex reachable from s
 89                         last=u;
 90                     --it;
 91                 }
 92                 while (path.back()!=last)
 93                     path.pop_back();
 94             }
 95         }
 96     }
 97     return maxflow;
 98 }
 99 
100 int main()
101 {
102     int i, fi, di, j, food, drink, maxflow;
103     src=0;
104     //freopen("input.txt", "r", stdin);
105     while (scanf("%d %d %d"&N, &F, &D)!=EOF){
106         sink=N+N+F+D+1;
107         memset(resflow, 0sizeof(resflow));
108         for (i=1;i<=D;i++)
109             resflow[src][i]=1;
110         for (i=1;i<=F;i++)
111             resflow[D+N+N+i][sink]=1;
112         for (i=1;i<=N;i++)
113             resflow[D+i][D+N+i]=1;
114 
115         for (i=1;i<=N;i++){
116             scanf("%d %d"&fi, &di);
117             for (j=1;j<=fi;j++){
118                 scanf("%d"&food);
119                 resflow[D+N+i][D+N+N+food]=1;
120             }
121             for (j=1;j<=di;j++){
122                 scanf("%d"&drink);
123                 resflow[drink][D+i]=1;
124             }
125         }
126         maxflow=Dinic();
127         printf("%d\n", maxflow);
128     }
129     return 0;
130 }

//AC T:63MS
#include <iostream>
#include 
<list>
#define GSIZE 402
#define INF 10000000
using namespace std;
int N, F, D, src, sink;
int resflow[GSIZE][GSIZE], color[GSIZE], level[GSIZE];
int OutDegree(int x)//compute the out degree of a node in level graph
{
    
int i;
    
for (i=0;i<=sink;i++){
        
if (resflow[x][i]!=0 && level[x]+1==level[i])
            
return i;
    }
    
return 0;
}

int BFS()//Construct the level graph
{
    
int i, u, v, flag;
    list
<int> l;//queue
    flag=0;
    
for (i=1;i<=sink;i++){//necessary?
        level[i]=INF;
        color[i]
=0;
    }
    color[src]
=1;
    l.push_back(src);
    
while(!l.empty()){
        u
=l.front();
        l.pop_front();
        
for (v=0;v<=sink;v++){
            
if (resflow[u][v]!=0 && color[v]==0){
                color[v]
=1;
                level[v]
=level[u]+1;
                l.push_back(v);
            }
        }
        
if (u==sink)
            flag
=1;
        color[u]
=2;
    }
    
return flag;
}

int Dinic()
{
    
int maxflow, u, v, capflow, last;
    list
<int> path;//stack
    list<int>::iterator it;
    maxflow
=0;
    
while(BFS()){
        path.push_back(src);
        
while (OutDegree(src)>0){
            u
=path.back();
            
//search the path from s to t in level graph
            if (u!=sink){
                
if ((v=OutDegree(u))!=0)
                    path.push_back(v);
                
else{
                    path.pop_back();
                    level[u]
=INF;
                }
            }
            
//update the residual graph along path
            else{
                capflow
=INF;
                
for (it=path.begin();it!=path.end();it++){
                    u
=*it;
                    
if ((++it)==path.end())
                        
break;
                    v
=*it;
                    
if (resflow[u][v]<capflow)
                        capflow
=resflow[u][v];
                    
--it;
                }
                last
=-1;
                maxflow
+=capflow;
                
for (it=path.begin();it!=path.end();it++){
                    u
=*it;
                    
if ((++it)==path.end())
                        
break;
                    v
=*it;
                    resflow[u][v]
-=capflow;
                    resflow[v][u]
+=capflow;
                    
if (resflow[u][v]==0 && last==-1)//label the last vertex reachable from s
                        last=v;
                    
--it;
                }
                
while (path.back()!=last)
                    path.pop_back();
                path.pop_back();
            }
        }
    }
    
return maxflow;
}

int main()
{
    
int i, fi, di, j, food, drink, maxflow;
    src
=0;
    
//freopen("input.txt", "r", stdin);
    while (scanf("%d %d %d"&N, &F, &D)!=EOF){
        sink
=N+N+F+D+1;
        memset(resflow, 
0sizeof(resflow));
        
for (i=1;i<=D;i++)
            resflow[src][i]
=1;
        
for (i=1;i<=F;i++)
            resflow[D
+N+N+i][sink]=1;
        
for (i=1;i<=N;i++)
            resflow[D
+i][D+N+i]=1;

        
for (i=1;i<=N;i++){
            scanf(
"%d %d"&fi, &di);
            
for (j=1;j<=fi;j++){
                scanf(
"%d"&food);
                resflow[D
+N+i][D+N+N+food]=1;
            }
            
for (j=1;j<=di;j++){
                scanf(
"%d"&drink);
                resflow[drink][D
+i]=1;
            }
        }
        maxflow
=Dinic();
        printf(
"%d\n", maxflow);
    }
    
return

Dinic参考: http://en.wikipedia.org/wiki/Dinitz_blocking_flow_algorithm
     王欣上《浅谈基于分层思想的网络流算法》
     MH.Alsuwaiyel《算法设计技巧与分析》(Algorithms Design Techniques and Analysis)

转载于:https://www.cnblogs.com/zen_chou/archive/2009/07/17/1525841.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值