`
huobengluantiao8
  • 浏览: 1034571 次
文章分类
社区版块
存档分类
最新评论

POJ 3204 最大流

 
阅读更多

题目大意是这样,找这样一种边的个数,就是增加该边的容量,可以使得最大流变大

那么首先我们求一遍最大流,如果某条边符合我们的要求,那么这条边必然是满流的,否则增加容量也没有用,然后假设端点为u->v,那么必然存在从源点到u的不饱和的路径,也就是路径上的每条边都是不满的,同样从v到汇点也应该有这样的路径,也只有这样才会在该边增加容量后形成一条增广路。

那么我们搞定这个问题的方法就是DFS了,从源点出发,沿着那些不满的边进行DFS,这样遍历到的点均是可以与源点有一条不饱和的路径的。

同理从汇点出发,进行逆向的DFS,这时最好先建个逆图。

最后枚举边即可。


#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#define eps 1e-5
#define MAXN 1111
#define MAXM 55555
#define INF 10000007
using namespace std;
struct node
{
    int v;    // vtex
    int c;    // cacity
    int f;   // current f in this arc
    int next, r;
}edge[MAXM];
int dist[MAXN], nm[MAXN], src, des, n;
int head[MAXN], e;
void add(int x, int y, int c)
{
    edge[e].v = y;
    edge[e].c = c;
    edge[e].f = 0;
    edge[e].r = e + 1;
    edge[e].next = head[x];
    head[x] = e++;
    edge[e].v = x;
    edge[e].c = 0;
    edge[e].f = 0;
    edge[e].r = e - 1;
    edge[e].next = head[y];
    head[y] = e++;
}
void rev_BFS()
{
    int Q[MAXN], h = 0, t = 0;
    for(int i = 1; i <= n; ++i)
    {
        dist[i] = MAXN;
        nm[i] = 0;
    }
    Q[t++] = des;
    dist[des] = 0;
    nm[0] = 1;
    while(h != t)
    {
        int v = Q[h++];
        for(int i = head[v]; i != -1; i = edge[i].next)
        {
            if(edge[edge[i].r].c == 0 || dist[edge[i].v] < MAXN)continue;
            dist[edge[i].v] = dist[v] + 1;
            ++nm[dist[edge[i].v]];
            Q[t++] = edge[i].v;
        }
    }
}
void init()
{
    e = 0;
    memset(head, -1, sizeof(head));
}
int maxflow()
{
    rev_BFS();
    int u;
    int total = 0;
    int cur[MAXN], rpath[MAXN];
    for(int i = 1; i <= n; ++i)cur[i] = head[i];
    u = src;
    while(dist[src] < n)
    {
        if(u == des)     // find an augmenting path
        {
            int tf = INF;
            for(int i = src; i != des; i = edge[cur[i]].v)
                tf = min(tf, edge[cur[i]].c);
            for(int i = src; i != des; i = edge[cur[i]].v)
            {
                edge[cur[i]].c -= tf;
                edge[edge[cur[i]].r].c += tf;
                edge[cur[i]].f += tf;
                edge[edge[cur[i]].r].f -= tf;
            }
            total += tf;
            u = src;
        }
        int i;
        for(i = cur[u]; i != -1; i = edge[i].next)
            if(edge[i].c > 0 && dist[u] == dist[edge[i].v] + 1)break;
        if(i != -1)     // find an admissible arc, then Advance
        {
            cur[u] = i;
            rpath[edge[i].v] = edge[i].r;
            u = edge[i].v;
        }
        else        // no admissible arc, then relabel this vtex
        {
            if(0 == (--nm[dist[u]]))break;    // GAP cut, Important!
            cur[u] = head[u];
            int mindist = n;
            for(int j = head[u]; j != -1; j = edge[j].next)
                if(edge[j].c > 0)mindist = min(mindist, dist[edge[j].v]);
            dist[u] = mindist + 1;
            ++nm[dist[u]];
            if(u != src)
                u = edge[rpath[u]].v;    // Backtrack
        }
    }
    return total;
}
int nt, m;
vector<int>g[MAXN], rg[MAXN];
int uu[MAXM], vv[MAXM];
int color1[MAXN], color2[MAXN];
void dfs1(int u)
{
    color1[u] = 1;
    int size = g[u].size();
    for(int i = 0; i < size; i++)
    {
        int v = g[u][i];
        if(!color1[v]) dfs1(v);
    }
}
void dfs2(int u)
{
    color2[u] = 1;
    int size = rg[u].size();
    for(int i = 0; i < size; i++)
    {
        int v = rg[u][i];
        if(!color2[v]) dfs2(v);
    }
}
int main()
{
    int u, v, w;
    scanf("%d%d", &nt, &m);
    init();
    src = 1;
    des = nt;
    n = nt;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d%d%d", &u, &v, &w);
        uu[i] = u + 1, vv[i] = v + 1;
        add(uu[i], vv[i], w);
    }
    maxflow();
    for(int i = 0; i < MAXN; i++)
        g[i].clear(), rg[i].clear();
    for(int i = 0; i < e; i += 2)
        if(edge[i].c > 0)
        {
            int id = i / 2 + 1;
            g[uu[id]].push_back(vv[id]);
            rg[vv[id]].push_back(uu[id]);
        }
    dfs1(src), dfs2(des);
    int ans = 0;
    for(int i = 0; i < e; i += 2)
        if(edge[i].c == 0)
        {
            int id = i / 2 + 1;
            if(color1[uu[id]] && color2[vv[id]]) ans++;
        }
    printf("%d\n", ans);
    return 0;
}


分享到:
评论

相关推荐

    POJ2516__最小费用最大流

    poj2516代码最小费用最大流

    POJ3308-Paratroopers 【Dinic算法求最大流】

    【二分图顶点覆盖-&gt;最小割-&gt;最大流-&gt;Dinic算法求解】 解题报告+AC代码 http://hi.csdn.net/!s/WKVPR0 ----&gt; 我的所有POJ解题报告 http://blog.csdn.net/lyy289065406/article/details/6642573

    POJ2195-Going Home【费用流】

    北大POJ2195-Going Home【费用流】 解题报告+AC代码 http://blog.csdn.net/lyy289065406/article/details/6732762

    网络流(最大流)SAP源码

    最短增广路算法的实现 并加上了gap优化和当前弧优化 代码为POJ3469(dual core)的源码

    北大oj 题目分类

    初期: 一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法.... (4)递推.... (5)构造法.(poj3295) ... (6)最大流的增广路算法(KM算法). (poj1459,poj3436) ......

    acm_code_20053565

    acm code of 20053565 poj onlinejudge 高精度 DP 图论 算法 最大流 最小生成树 线段树

    大学课程中相关一些算法题

    4.1 最大乘积问题 4.2 魔术数字游戏 4.3 Jimmy's Bad Day 5.1 循环赛的日程表问题 5.2 猴子选大王 5.3 售货员的难题 6.1 最大字段和问题 6.2 N*N方阵 6.3 埃及分数最好表达式

    浙江大学ACM模板 计算几何,图论,数据结构,经典题的模板

    8.10 最大网络流 175 8.11 最小费用流 180 8.12 最大团问题 182 8.13 二分图匹配 184 8.14 带权的最优二分图匹配 184 9.搜索算法概略 187 9.1 迭代深搜+IDA* 187 9.2 分之界限法(深搜) 189 9.3 A* 8数码问题( ...

    挑战程序设计竞赛(第2版)

    3.5.1 最大流 3.5.2 最小割 3.5.3 二分图匹配 3.5.4 一般图匹配 3.5.5 匹配、边覆盖、独立集和顶点覆盖 3.5.6 最小费用流 3.5.7 应用问题 3.6 与平面和空间打交道的计算几何 3.6.1 计算几何基础 3.6.2 极限情况 ...

    leetcode2sumc-coding:用C++编码

    个最大元素:# 递归 排列:#、# 哈希 二和:# 同构字符串:# 注意:构建堆,O(n); 提取根并重建 O(logn) 从数据流中查找中位数:# 合并 k 个排序的数组/列表:# 链表 #,# 树 遍历:前序、中序、后序、水平 同一棵...

    kuangbin acm模板超级好用

    2.6 随机素数测试和大数分解 (POJ 1811) . . . . . . . . . . . . . . . . . . . . . . . 29 2.7 欧拉函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 2.7.1 分解质因素求...

Global site tag (gtag.js) - Google Analytics