POJ 1273 Drainage Ditche(最大流模板题)

题意:现在有m个池塘(1m开始编号,1为源点,m为汇点),n条水渠,给出这n条水渠所连接的池塘和所能流过的水量,求水渠中所能流过的水的最大容量.


Edmonds-Karp算法:

#include
#include
#include
#include
#include
#include
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 505;
int g[maxn][maxn], n, m;
int path[maxn], flow[maxn];
int start, endd;

int bfs()
{
    queue q;
    memset(path, -1, sizeof(path));
    path[start] = 0, flow[start] = INF; //  起始容量为inf
    q.push(start);
    while(!q.empty())
    {
        int t = q.front(); q.pop();
        if(t == endd) break;
        for(int i = 1; i <= m; i++) //  遍历可走路径;
        {
            if(i!=start && path[i]==-1 && g[t][i])   //  符合这三种情况表示该路径可走
            {
                flow[i] = min(flow[t], g[t][i]);
                q.push(i);
                path[i] = t;
            }
        }
    }
    if(path[endd] == -1) return -1; //  说明没有找到可走路径,返回-1;
    return flow[endd]; //  找到一条路径之后的增流量;
}

int E_K()
{
    int max_flow = 0, step, now, pre;
    while((step=bfs()) != -1)//  找不到路径之后便退出;
    {
        max_flow += step; //  累加流量
        now = endd;
        while(now != start) //  将找到的路径进行反向处理,并更新实际容量;
        {
            pre = path[now];
            g[pre][now] -= step; //  更新正向边的实际容量;
            g[now][pre] += step;//  添加反向边
            now = pre;
        }
    }
    return max_flow;
}

int main(void)
{
    while(cin >> n >> m)
    {
        memset(g, 0, sizeof(g));
        for(int i = 1; i <= n; i++)
        {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            g[u][v] += w;
        }
        start = 1, endd = m;
        printf("%d\n", E_K());
    }
    return 0;
}



Ford-Fulkerson的dfs写法:(白书上有)

#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 505;
const int INF = 0x3f3f3f3f;
int n, m;
bool vis[maxn];
struct node
{
    int to, cap, rev;   //终点,容量,反向边
    node() {}
    node(int tt, int cc, int rr): to(tt), cap(cc), rev(rr) {}
};
vector g[maxn];

int dfs(int v, int t, int f)
{
    if(v == t) return f;
    vis[v] = 1;
    for(int i = 0; i < g[v].size(); i++)
    {
        node &e = g[v][i];  //一定要带&,因为要对他进行修改
        if(!vis[e.to] && e.cap > 0)
        {
            int d = dfs(e.to, t, min(f, e.cap));
            if(d > 0)
            {
                e.cap -= d;
                g[e.to][e.rev].cap += d;
                return d;
            }
        }
    }
    return 0;
}

ll max_flow(int s, int t)
{
    ll flow = 0;
    while(1)
    {
        memset(vis, 0, sizeof(vis));
        int f = dfs(s, t, INF);
        if(!f) return flow;
        flow += f;
    }
}

int main(void)
{
    while(cin >> n >> m)
    {
        for(int i = 0; i < maxn; i++)
            g[i].clear();
        for(int i = 0; i < n; i++)
        {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            g[u].push_back(node(v, w, g[v].size()));
            g[v].push_back(node(u, 0, g[u].size()-1));
        }
        printf("%lld\n", max_flow(1, m));
    }
    return 0;
}



SAP模板:

#include
#include
#include
#include
using namespace std;
const int INF = 0x7fffffff;
const int maxv = 2600;
const int maxe = 1000000;
int n,m;
struct Edge
{
    int v;
    int next;
    int flow;
};
Edge e[maxe];
int head[maxv],edgeNum;
int now[maxv],d[maxv],vh[maxv],pre[maxv],preh[maxv];

void addEdge(int a,int b,int c)
{
    e[edgeNum].v = b;
    e[edgeNum].flow = c;
    e[edgeNum].next = head[a];
    head[a] = edgeNum++;
    e[edgeNum].v = a;
    e[edgeNum].flow = 0;
    e[edgeNum].next = head[b];
    head[b] = edgeNum++;
}

void Init()
{
    edgeNum = 0;
    memset(head,-1,sizeof(head));
    memset(d,0,sizeof(d));
}

int sap(int s,int t,int n)       //源点,汇点,结点总数
{
    int i,x,y;
    int f,ans = 0;
    for(i = 0; i < n; i++)
        now[i] = head[i];
    vh[0] = n;
    x = s;
    while(d[s] < n)
    {
        for(i = now[x]; i != -1; i = e[i].next)
            if(e[i].flow > 0 && d[y=e[i].v] + 1 == d[x])
                break;
            if(i != -1)
            {
                now[x] = preh[y] = i;
                pre[y] = x;
                if((x=y) == t)
                {
                    for(f = INF,i=t; i != s; i = pre[i])
                        if(e[preh[i]].flow < f)
                            f = e[preh[i]].flow;
                    ans += f;
                    do
                    {
                        e[preh[x]].flow -= f;
                        e[preh[x]^1].flow += f;
                        x = pre[x];
                    }while(x!=s);
                }
            }
            else
            {
                if(!--vh[d[x]])
                    break;
                d[x] = n;
                for(i=now[x]=head[x]; i != -1; i = e[i].next)
                {
                    if(e[i].flow > 0 && d[x] > d[e[i].v] + 1)
                    {
                        now[x] = i;
                        d[x] = d[e[i].v] + 1;
                    }
                }
                ++vh[d[x]];
                if(x != s)
                    x = pre[x];
            }
    }
    return ans;
}

int main(void)
{
    int n, m;
    while(cin >> n >> m)
    {
        Init();
        while(n--)
        {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            addEdge(u, v, w);
        }
        printf("%d\n", sap(1, m, m));
    }
    return 0;
}



Sample Input
5 4
1 2 40
1 4 20
2 4 20
2 3 30
3 4 10
Sample Output
50

你可能感兴趣的:(POJ 1273 Drainage Ditche(最大流模板题))