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;
    }
  • 相关阅读:
    Windows Store App 主题动画
    Windows Store App 过渡动画
    Windows Store App 控件动画
    Windows Store App 近期访问列表
    Windows Store App 文件选取器
    Windows Store App 访问应用内部文件
    Windows Store App 用户库文件分组
    Windows Store App 获取文件及文件夹列表
    Windows Store App 用户库文件夹操作
    Windows Store App 用户库文件操作
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/8099374.html
Copyright © 2011-2022 走看看