Dinic&EK模板记录

题目描述:

有多组数据,每组数据中:

1为源点,n为汇点。
有 m条单向边,连接 u->v,其容量为c
求1到n的最大流

保证结果在int范围内 (Poj1273 Drainage Ditches)

模板:

//Dinic 模板
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;

const int maxn=1e3+10;
const int maxe=1e3+10;
const int INF=0x7fffffff;

struct Edge
{
    int from,to,cap,flow,next;
    Edge() {}
    Edge(int f,int t,int c,int fl,int n):from(f),to(t),cap(c),flow(fl),next(n) {}
}edges[maxe]; int pre[maxn],cnt;

int n,m;
int level[maxn];           //层次图  

void init()
{
    cnt=0; memset(pre,-1,sizeof(pre));
    for (int i=1;i<=m;i++)
    {
        int u,v,cap;
        scanf("%d%d%d",&u,&v,&cap);
        edges[cnt]=Edge(u,v,cap,0,pre[u]); pre[u]=cnt++;  
        edges[cnt]=Edge(v,u,0,0,pre[v]); pre[v]=cnt++;   //反向弧
    }
}

int bfs(int s,int t)       //建立层次图   类似SPFA
{
    memset(level,0,sizeof(level));
    level[s]=1;             //起点在第一层
    queue<int> q; q.push(s);
    while (!q.empty())
    {
        int u=q.front(); q.pop();
        if (u==t) return 1;
        for (int i=pre[u];~i;i=edges[i].next)
        {
            int v=edges[i].to;
            if (!level[v]&&edges[i].cap>edges[i].flow)  //可改进
            {
                level[v]=level[u]+1;
                q.push(v);
            }
        }
    } return 0;
}

int dfs(int s,int maxf,int t)      //寻找一条可行流   maxf为改进流量上限
{
    if (s==t) return maxf;         //到汇点
    int ret=0;
    for (int i=pre[s];~i;i=edges[i].next)
    {
        int v=edges[i].to;
        if (level[v]==level[s]+1&&edges[i].cap>edges[i].flow)  //可改进
        {
            int Min=min(maxf-ret,edges[i].cap-edges[i].flow); //可行流上最小的改进流量
            int fl=dfs(v,Min,t);   
            edges[i].flow+=fl;      //更新残量网络
            edges[i^1].flow-=fl;     
            ret+=fl;                //累加改进流量
            if (ret==maxf) return ret;
        }
    }
    return ret;
}

int dinic(int s,int t)
{
    int ans=0;
    while (bfs(s,t))            //无出现断层  可以建立层次图
        ans+=dfs(s,INF,t);      //寻找改进可行流
    return ans;                 //输出最大流
}

void work()
{
    printf("%d\n",dinic(1,n));
}

int main()
{
    while (~scanf("%d%d",&m,&n))
    {
        init();
        work(); 
    }
    return 0;
}
//EK 模板
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

#define E edges[i]
const int maxn=205;
const int INF=0x7FFFFFFF;

struct Edge
{
    int from,to,cap,next,flow;
    Edge() {}
    Edge(int fr,int t,int ca,int flo,int nex):from(fr),to(t),cap(ca),flow(flo),next(nex) {}
}edges[500]; int cnt,pre[maxn];

int n,m,a[maxn],p[maxn];
//a[]记录改进流量
//p[]记录可行流路径

int maxflow(int s,int t)    //求最大流
{
    int flow=0;
    for (;;)
    {
        memset(a,0,sizeof(a));
        queue<int> q;
        q.push(s); a[s]=INF;
        while (!q.empty())
        {
            int now=q.front(); q.pop();
            for (int i=pre[now];i!=-1;i=E.next)
            {
                if (!a[E.to]&&E.cap>E.flow)
                {
                    p[E.to]=i;
                    a[E.to]=min(a[now],E.cap-E.flow);
                    q.push(E.to);
                }
            }
            if (a[t]) break;
        }
        if (!a[t]) break;
        for (int i=t;i!=s;i=edges[p[i]].from)
        {
            edges[p[i]].flow+=a[t];     //更新残量网络
            edges[p[i]^1].flow-=a[t];
        }
        flow+=a[t];
    }
    return flow;
}

int main()
{
    while (~scanf("%d%d",&n,&m))
    {
        cnt=0;
        for (int i=1;i<=m;i++) pre[i]=-1;
        for (int i=1;i<=n;i++)
        {
            int s,e,c;
            scanf("%d%d%d",&s,&e,&c);
            edges[cnt]=Edge(s,e,c,0,pre[s]); pre[s]=cnt; cnt++;
            edges[cnt]=Edge(e,s,0,0,pre[e]); pre[e]=cnt; cnt++;
        }
        printf("%d\n",maxflow(1,m));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值