关于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
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, 0, sizeof(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, 0, sizeof(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);
}
returnDinic参考: http://en.wikipedia.org/wiki/Dinitz_blocking_flow_algorithm
王欣上《浅谈基于分层思想的网络流算法》
MH.Alsuwaiyel《算法设计技巧与分析》(Algorithms Design Techniques and Analysis)