(网络流模板1)最大流(Dinic模板)

A 最大流 (10 分)

这是一道模板题。

给定 n 个点,m 条边,给定每条边的容量,求从点 s 到点 t 的最大流。

输入格式:

第一行四个整数n,m,s,t。

接下来的 m 行,每行三个整数u,v,c,表示从 u 到 v,流量为 c 的一条边。

数据保证有 1≤n≤100,1≤m≤5000,0≤c≤2​31​​−1。

输出格式:

输出点 s 到点 t 的最大流。

输入样例:

7 14 1 7
1 2 5
1 3 6
1 4 5
2 3 2
2 5 3
3 2 2
3 4 3
3 5 3
3 6 7
4 6 5
5 6 1
6 5 1
5 7 8
6 7 7

输出样例:

14

 这个是网络流的模板题,网络流主要是计算一个图的最大流量,一条路径的流量取决于这条路径所有边中最小的容量,最终计算的能从起点流到终点的最大流量为各路径流量之和

完整代码:

#include 
#define int long long
const int inf=0x3f3f3f3f;
const int maxn=3e5+10;
using namespace std;
typedef struct edge
{
    int first,c,next;//fisrt为边的终点,next为同起点的上一条边的编号
}edg;
edg e[maxn<<1];//e[]是代表边的结构体,first和next分别为该边的终点和与该边同起点的上一条边的编号,c为该边的容量
int n,m,s,t,head[maxn],q[maxn],vis[maxn],sum;//head[i]记录以i为起点的当前边的编号,q[]是模拟队列,vis[]标记数组,sum记录边数(总的边的编号)

void AddEdge(int u,int v,int c)//加边函数
{
    e[sum]=(edg){v,c,head[u]};//(edge)表示强制转化为edge(结构体)类型,表示将后面的v,c,head[u]这三个变量强制转化为edge类型后赋值给e[sum]
    head[u]=sum++;//以u为起点的当前边的编号更新为当前边的编号sum
}

bool bfs()//bfs判断路径是否存在
{
    memset(vis,0,sizeof(vis));//对标记数组初始化
    q[1]=s;//s进队
    vis[s]=1;//标记
    int front=0,rear=1;
    while(front!=rear)
    {
        front++;
        for(int i=head[q[front]];i!=-1;i=e[i].next)//倒序遍历以当前队头元素为起点的所有边
        {//head[q[front]]表示以队头元素为起点的最后一条边的编号
            if(e[i].c&&!vis[e[i].first])
            {
                rear++;
                vis[e[i].first]=vis[q[front]]+1;//让现在的边的标记改为队头元素的+1
                q[rear]=e[i].first;//入队
                if(e[i].first==t)//找到终点了,说明该路径存在
                {
                    return true;
                }
            }
        }
    }
    return false;
}

int dfs(int f,int u)//dfs计算当前图的最大流,f为当前流量,u为当前点的编号
{
    if(u==t)
    {
        return f;
    }
    int d=0,used=0;
    for(int i=head[u];i!=-1;i=e[i].next)
    {
        if(e[i].c&&vis[u]==vis[e[i].first]-1)//因为根据bfs中的标记(vis[e[i].first]=vis[q[front]]+1),所以vis[u]==vis[e[i].first]-1说明u是i这个点的前一个点,也就是说能走到当前点,当前点合法
        {//多路增广优化:
            if(d=dfs(min(f-used,e[i].c),e[i].first))//f-used表示当前流量减去返回的总流量,d计算当前路径反边的权值
            {//前路径反边返回值为当前路径中最小的那个容量
                e[i].c-=d;//当前容量减去当前路径反边返回值
                e[i^1].c+=d;//反边加上去当前路径反边返回值
                used+=d;
            }
        }
    }
    if(!used)//炸点优化
    {
        vis[u]=0;//如果当前流量为0,那么就流不到该点了,则直接把当前点去掉
    }
    return used;
}

int Dinic()
{
    int maxflow=0;//maxflow计算整个图的最大流
    while(bfs())
    {
        int d=0;
        while(d=dfs(inf,s))
        {
            maxflow+=d;//最大流是其每个路经的一个累加
        }
    }
    return maxflow;
}

signed main()
{
    cin>>n>>m>>s>>t;
    memset(head,-1,sizeof(head));
    while(m--)
    {
        int u,v,c;
        cin>>u>>v>>c;
        AddEdge(u,v,c);//添加正边
        AddEdge(v,u,0);//添加反边
    }
    cout<

 

你可能感兴趣的:((网络流模板1)最大流(Dinic模板))