最大流

最大流

题目链接

EK算法:

在残余网络中不断寻找增广路径(使用bfs)直到不能再增广,并把每次找到的增广路径的流量加起来就是最大流。

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<cstring>
#include<algorithm>

#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define fori(x,s,t) for(int x=s;x<=t;x++)
#define ford(x,s,t) for(int x=s;x>=t;x--)
#define ll long long
using namespace std;

const int M=1e4+10,inf=1e8;

struct N
{
    int v,c,re;
};
vector<N> g[M];
int pre[M],pe[M],flow[M],n,m;

int bfs(int s,int t)  //bfs寻找增广路径
{
    memset(pre,-1,sizeof(pre));
    pre[s]=0;
    flow[s]=inf;
    queue<int> q;
    q.push(s);
    while(!q.empty())
    {
        int p=q.front();q.pop();
        if(p==t)break;
        for(int i=0,j=g[p].size();i<j;i++)
        {
            if(g[p][i].c<=0||pre[g[p][i].v]!=-1)continue;
            flow[g[p][i].v]=min(g[p][i].c,flow[p]);
            pre[g[p][i].v]=p;
            pe[g[p][i].v]=i;
            q.push(g[p][i].v);
        }
    }
    if(pre[t]==-1)return -1;  //找不到增广路径,返回-1
    return flow[t];   //找到增广路径,返回增广路径的流量
}

int ek(int s,int t)
{
    int ans=0,da;
    while(1)
    {
        da=bfs(s,t);  //寻找增广路径
        if(da<=0)break;//找不到增广路径,结束
        int p=t;
        while(p!=s)  //找到增广路径,更新残余网络
        {
            N &tem=g[pre[p]][pe[p]];
            tem.c-=da;
            g[p][tem.re].c+=da;
            p=pre[p];
        }
        ans+=da;
    }
    return ans;
}

void add(int x,int y,int z)//加边
{
    g[x].push_back((N){y,z,g[y].size()});
    g[y].push_back((N){x,0,g[x].size()-1});
}

int main()
{
    int s,t,u,v,c;
    scanf("%d%d%d%d",&n,&m,&s,&t);
    while(m--)
    {
        scanf("%d%d%d",&u,&v,&c);
        add(u,v,c);
    }
    printf("%d\n",ek(s,t));
    return 0;
}


dinic算法:

        和EK算法属于同类型的最大流算法,都是通过寻找增广路径来求最大流的。
与EK算法不同的是,dinic算法先使用bfs将图进行分层,然后在分层图上使用dfs寻找增广路径。

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<cstring>
#include<algorithm>

#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define fori(x,s,t) for(int x=s;x<=t;x++)
#define ford(x,s,t) for(int x=s;x>=t;x--)
#define ll long long
using namespace std;

const int M=1e4+30,inf=1e8;

struct N
{
    int v,c,rv;
};

vector<N> g[M];

int n,m,dep[M],now[M];

bool bfs(int s,int t)  //将图分层,dep记录每个顶点的层数(层数从0或1开始都是没问题的)
{
    memset(dep,-1,sizeof(dep));
    dep[s]=0;
    queue<int> q;
    q.push(s);
    while(!q.empty())
    {
        int p=q.front();q.pop();
        for(int i=0,j=g[p].size();i<j;i++)
        {
            int u=g[p][i].v,c=g[p][i].c;
            if(c<=0||dep[u]!=-1)continue;   //如果边的容量已经小于等于0了,那么就不能再对其指向的顶点分层
            dep[u]=dep[p]+1;
            q.push(u);
        }
    }
    memset(now,0,sizeof(now));
    return dep[t]!=-1;   //返回从s到t是否可以分层
}

ll dfs(int s,int t,ll f)  //寻找增广路径
{
    if(s==t)return f;    //递归出口,当dfs到t的时候则说明找到了s到t的增广路径,返回增广路径的流量
    for(int i=now[s],j=g[s].size();i<j;i++)
    {
        now[s]=i;    //当前弧优化
        int u=g[s][i].v,c=g[s][i].c,ru=g[s][i].rv;
        if(c<=0||dep[u]!=dep[s]+1)continue;
        ll tem=dfs(u,t,min(f,(ll)c));     //递归寻找u,到t的增广路径
        if(tem>0)    //找到增广路径,更新网络
        {
            g[s][i].c-=tem;
            g[u][ru].c+=tem;
            return tem;
        }
    }
    return 0;
}

ll dinic(int s,int t)
{
    ll ans=0,tem;
    while(bfs(s,t))  //对图进行分层,若不能分层,那么就不存在s到t 的增光路径,结束
        while((tem=dfs(s,t,inf))>0)ans+=tem;  //在分层图中寻找增广路径
    return ans;
}

void add(int x,int y,int z)  //加边
{
    g[x].push_back((N){y,z,g[y].size()});
    g[y].push_back((N){x,0,g[x].size()-1});
}

int main()
{
    int s,t;
    scanf("%d%d%d%d",&n,&m,&s,&t);
    int x,y,z;
    while(m--)
    {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
    }
    printf("%lld\n",dinic(s,t));
    return 0;
}


 

基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究(Matlab代码实现)内容概要:本文围绕“基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究”,介绍了利用Matlab代码实现配电网可靠性的仿真分析方法。重点采用序贯蒙特卡洛模拟法对配电网进行长时间段的状态抽样与统计,通过模拟系统元件的故障与修复过程,评估配电网的关键可靠性指标,如系统停电频率、停电持续时间、负荷点可靠性等。该方法能够有效处理复杂网络结构与设备时序特性,提升评估精度,适用于含分布式电源、电动汽车等新型负荷接入的现代配电网。文中提供了完整的Matlab实现代码与案例分析,便于复现和扩展应用。; 适合人群:具备电力系统基础知识和Matlab编程能力的高校研究生、科研人员及电力行业技术人员,尤其适合从事配电网规划、运行与可靠性分析相关工作的人员; 使用场景及目标:①掌握序贯蒙特卡洛模拟法在电力系统可靠性评估中的基本原理与实现流程;②学习如何通过Matlab构建配电网仿真模型并进行状态转移模拟;③应用于含新能源接入的复杂配电网可靠性定量评估与优化设计; 阅读建议:建议结合文中提供的Matlab代码逐段调试运行,理解状态抽样、故障判断、修复逻辑及指标统计的具体实现方式,同时可扩展至不同网络结构或加入更多不确定性因素进行深化研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值