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

来源:互联网 发布:知乎北京五中大厂分校 编辑:程序博客网 时间:2024/06/18 12:23

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


Edmonds-Karp算法:

#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<algorithm>#include<queue>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<int> 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<iostream>#include<cstdio>#include<cstring>#include<vector>#include<algorithm>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<node> 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<iostream>#include<cstdio>#include<cstring>#include<vector>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

0 0