现在的位置: 首页 > 综合 > 正文

poj 1459 power network(网络流 di…

2018年03月17日 ⁄ 综合 ⁄ 共 1631字 ⁄ 字号 评论关闭
题目大意:
      
给几个发电站,给几个消耗站,再给几个转发点。

      
发电站只发电,消耗站只消耗电,转发点只是转发电,再给各个传送线的传电能力。

      
问你消耗站能获得的最多电是多少

思路:建立一个超级源点和超级汇点,把发电站相连起来,消耗站连起来 然后就是模版的力量了

在此也讲了下dinic的原理:
求最大流的本质,就是不停的寻找增广路径。直到找不到增广路径为止。
对于这个一般性的过程,Dinic算法的优化如下:

(1)
Dinic算法首先对图进行一次BFS,然后在BFS生成的层次图中进行多次DFS。
层次图的意思就是,只有在BFS树中深度相差1的节点才是连接的。
这就切断了原有的图中的许多不必要的连接。很牛逼!
这是需要证明的,估计证明也很复杂。

(2)
除此之外,每次DFS完后,会找到路径中容量最小的一条边。
在这条边之前的路径的容量是大于等于这条边的容量的。
那么从这条边之前的点,可能引发出别的增广路径。
比如说 S -> b -> c
-> d -> T 是一条增广路径,容量最小的边是 b
-> c。
可能存在一条 S -> b -> e ->
f -> g -> T 这样的增广路径。
这样的话,在找到第一条增广路径后,只需要回溯到 b 点,就可以继续找下去了。
这样做的好处是,避免了找到一条路径就从头开始寻找另外一条的开销。
也就是再次从 S 寻找到 b 的开销。
这个过程看似复杂,但是代码实现起来很优雅,因为它的本质就是回溯!
(3)
在同一次 DFS 中。如果从一个点引发不出任何的增广路径,就将这个点在层次图中抹去。

#include <stdio.h>
#include <string.h>
#define VM 150
#define EM 20550
#define inf 0x3f3f3f3f
struct edge
{
    int
frm,to,cap,next;
}e[EM];

int
head[VM],dep[VM],ep,n;    
//dep为点的层次
void addedge (int cu,int cv,int cw) 
//第一条边下标必须为偶数
{
    e[ep].frm =
cu;
    e[ep].to =
cv;
    e[ep].cap =
cw;
    e[ep].next =
head[cu];
    head[cu] =
ep;
    ep ++;
    e[ep].frm =
cv;
    e[ep].to =
cu;
    e[ep].cap =
0;
    e[ep].next =
head[cv];
    head[cv] =
ep;
    ep ++;
}

int BFS (int src,int
des)    
//求出层次图
{
    int
que[VM],i,front = 0,rear = 0;
    memset
(dep,-1,sizeof(dep));
    que[rear++]
= src;
    dep[src] =
0;
    while (front
!= rear)
    {
       
int u = que[front++];
       
front = front%VM;
       
for (i = head[u];i != -1;i = e[i].next)
       
{
           
int v = e[i].to;
           
if (e[i].cap >
0&&dep[v] == -1)
//容量大于0&&未在dep中
           
{
               
dep[v] = dep[u] +
1;       
//建立层次图
               
que[rear ++] = v;
               
rear = rear % VM;
               
if (v == des)  //找到汇点 返回
                   
return 1;
           
}
       
}
    }
    return
0;
}
int dinic (int src,int des)
{
    int i,res =
0,top;
    int
stack[VM];   
//stack为栈,存储当前增广路

抱歉!评论已关闭.