zoukankan      html  css  js  c++  java
  • 网络流(自行理解的Dinic)

    自行理解的Dinic 注释即讲解

    #include<bits/stdc++.h>
    const int maxn=100008;
    using namespace std;
    int read()
    {
        char ch=getchar();int f=1,w=0;
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch<='9'&&ch>='0'){w=w*10+ch-'0';ch=getchar();}
        return f*w;
    }                            //读入优化
    
    struct sj{
        int next;
        int to;
        int w;                    //w是剩余的流量
    }a[maxn*2];            
    int head[maxn],size=1;        //注意size 要赋值为1 否则会死循环
    int m,n;
    int s,t;
    int cent[maxn];                //层数
    int ans;
    
    void add(int x,int y,int z)
    {
        a[++size].to=y;
        a[size].next=head[x];
        head[x]=size;
        a[size].w=z;
    }                            //加边
    
    bool bfs()
    {
        memset(cent,-1,sizeof(cent));        //cent 层数先清零
        queue <int> q;
        q.push(s);
        cent[s]=0;                            //起点进栈
        while(q.empty()!=1)
        {
            int ks=q.front();            
            q.pop();
            for(int i=head[ks];i;i=a[i].next)
            {
                int ts=a[i].to;
                if(cent[ts]==-1&&a[i].w>0)
                {
                  q.push(ts);            
                  cent[ts]=cent[ks]+1;        //层数加1
                }
            }
        }
        if(cent[t]<0)                        //如果已经找不到增广路
        return 0;
        return 1;
    }
    
    int dfs(int x,int low)                    //dfs搜索 参数:当前的点,当前最小的流量
    {
        if(x==t)return low;                    //如果已经搜到终点了 就直接返回
        int flow=0,r;                        //避免重复流 每次都新定义一个统计的流量 每层都各自求和
        for(int i=head[x];i;i=a[i].next)
        {
            int st=a[i].to;
            if((a[i].w>0)&&(cent[st]==cent[x]+1))
            {
                r=dfs(st,min(a[i].w,low-flow));            //递归在这里  
                if(r>0)
                {
                    a[i].w-=r;                            //当前增广路走过的边 残量减掉这么多
                    a[i^1].w+=r;                        //反向边则加上这么多 
                    flow+=r;                            //流量加上r 这次找已经流了这么多
                }
            }
        }
        return flow;                                    //递归返回时 则返回已经流完的流量
    }
    
    
    int main()                                //主函数
    {
        n=read();m=read();
        s=read();t=read();
        for(int i=1;i<=m;i++)
        {
            int x,y,z;
            x=read();
            y=read();
            z=read();
            add(x,y,z);
            add(y,x,0);
        }                                    //建立反向边 
        while(bfs())
        {
            int row=dfs(s,0x3f3f3f);        //row代表这次搜索找到的流量总和
            ans+=row;
            cout<<row<<endl;
        }                                    //还能找到增广路
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    关于我的博客园皮肤效果
    Typora结合Git打造完美的个人云笔记本
    linux查看占用端口的进程号并杀死该进程
    关于将ISO 8601格式的时间字符串转化为yyyy-MM-dd hh:mm:ss格式字符串用于前后台传输数据方法
    前后端分离_Vue_axios本地跨域(前端localhost:8080到后端localhost:8090)
    T-SQL 查询分区详细信息和行计数
    INSERT INTO vs SELECT INTO
    SQL Server
    T-SQL 常用语句
    T-SQL Datetime转换成字符类型
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/8099374.html
Copyright © 2011-2022 走看看