Dinic算法解决最大流问题poj1273

来源:互联网 发布:陕西省科协网络平台 编辑:程序博客网 时间:2024/05/16 09:44

poj1273 经典的网络流例子
这里结网络流使用的是dinic 算法
相比于EdmondsKarp算法
每次bfs一次才可以找到一条增广路径的效率太低了
dinic算法 先使用bfs对图进行分层
分完层后 不断的进行dfs 搜索增广路径
直到图中不可以dfs的栈为空后 再进行重新分分层
然后再不断的进行dfs搜索增广路径
直到bfs不能再到达汇点 返回最大流

include <iostream>#include <deque>using namespace std;const int INF = 0xfffffff;const int MAXSIZE = 201;int G[MAXSIZE][MAXSIZE];int layer[MAXSIZE];//存储bfs的层次信息int visit[MAXSIZE];//在dfs中存储访问信息 用来回溯int n, m;//n为边的个数 m为点的个数bool bfs(){    deque<int> q;    q.push_back(1);    memset(layer, -1, sizeof(layer));//把所有没有访问过的点的层数设置为-1 作为没有访问的标识    layer[1] = 0;    while (!q.empty())    {        int temp = q.front();        q.pop_front();        for (int i = 1; i <= m; i++)        {            if (layer[i] == -1 && G[temp][i] > 0)//i没有被访问过且 temp到I有路径            {                layer[i] = layer[temp] + 1;                q.push_back(i);                if (i == m)//bfs从第源点找到了汇点                    return true;            }        }    }    return false;//从源点的bfs没有找到汇点}int dinic(){    int sum = 0;//存储最大流量    deque<int> q;    while (bfs())    {        memset(visit, 0, sizeof(visit));//清空visit数组        q.push_back(1);        visit[1] = 1;        while (!q.empty())        {            int temp = q.back();            if (temp == m)//找到了汇点            {                int min = INF;//增广路径中的增量                int mins;//增量的起点                for (int i = 1; i < q.size(); i++)//寻找增量                {                    int u = q[i - 1];                    int v = q[i];                    if (G[u][v] < min)                    {                        min = G[u][v];                        mins = u;                    }                }                sum += min;//增加总的流量                for (int i = 1; i < q.size(); i++)//更新网络                {                    int u = q[i - 1];                    int v = q[i];                    G[u][v] -= min;                    G[v][u] += min;                }                for (int a = q.back(); (!q.empty()) && (a != mins); q.pop_back())//回溯到增量的起点 寻找下条增广路径                    visit[a] = 0;            }            else//没有找到汇点            {                int i;                for (i = 1; i <= m; i++)                {                    if (!visit[i] && G[temp][i]>0 && layer[i] == layer[temp] + 1)                    {                        q.push_back(i);                        visit[i] = 1;                        break;                    }                }                if (i > m)//根据当前的dfs没有找到汇点 且访问完了所有节点 则回溯                    q.pop_back();            }        }    }    return sum;}int main(){    while (cin >> n >> m)//n为边数 m为点的个数    {        memset(G, 0, sizeof(G));        int u, v, w;        for (int i = 0; i < n; i++)        {            cin >> u >> v >> w;            G[u][v] += w;        }        cout << dinic() << endl;    }    return 0;}
1 0