zoukankan      html  css  js  c++  java
  • 网络流 最大流

    //dinic 最大流 
    //head[x]从0开始记 这样便于找反向边 异或即可 
    //当前弧优化 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #define ll long long
    #define ull unsigned long long
    #define INF 0x3f3f3f3f
    using namespace std;
    int n,m,s,t,ans,cnt=-1;//s源点,t汇点 
    int head[10001],cur[10001],dep[10001];
    struct uio{
        int nxt,to,wei;
    }edge[200001];
    void add(int x,int y,int z)
    {
        edge[++cnt].nxt=head[x];
        edge[cnt].to=y;
        edge[cnt].wei=z;
        head[x]=cnt;
    }
    bool bfs()//分层 
    {
        memset(dep,0x3f,sizeof(dep));
        queue<int> que;
        while(!que.empty())
            que.pop();
        memcpy(cur,head,sizeof(head));
        dep[s]=0;
        que.push(s);
        while(!que.empty())
        {
            int now=que.front();
            que.pop();
            for(int i=head[now];i!=-1;i=edge[i].nxt)
                if(dep[edge[i].to]==INF&&edge[i].wei)//还未被分层且为正向边 
                {
                    dep[edge[i].to]=dep[now]+1;
                    que.push(edge[i].to);
                }
        }
        if(dep[t]<INF)//有增广路 
            return true;
        else return false; 
    }
    int dfs(int now,int lim)//寻找可增加流量 
    //lim指源点到now的路径最小边权 
    {
        if(!lim||now==t)//到这个点没有可增广流量或已到汇点 
            return lim;
        int flow=0,change;//flow当前点可增广的流量 change每次增广流量 
        for(int i=cur[now];i!=-1;i=edge[i].nxt)
        {
            cur[now]=i;
            if(dep[edge[i].to]==dep[now]+1&&(change=dfs(edge[i].to,min(lim,edge[i].wei))))
            //如果下一个点可被增广且可增广流量大于0 
            {
                flow+=change;
                lim-=change;
                edge[i].wei-=change;
                edge[i^1].wei+=change;
                if(!lim) break;//没有容量可供增广就退出 
            }
        }
        return flow; 
    }
    void dinic()
    {
        while(bfs())//分层 
            ans+=dfs(s,INF);
    }
    int main()
    {
        memset(head,-1,sizeof(head)); 
        scanf("%d%d%d%d",&n,&m,&s,&t);
        for(int i=1;i<=m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);//正向边 
            add(v,u,0);//反向边 
        }
        dinic();
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    centos7 安装jdk 1.8
    CentOS查看Java进程并部署jar包
    Mybatis传多个参数(三种解决方案)
    mybatis使用注解往postgresql数据库表insert数据[主键自增]的写法
    在Linux上安装tomcat和JDK
    Linux下部署springboot项目的步骤及过程
    maven安装第三方jar包到本地仓库
    Android 开源动画框架:NineOldAndroids
    Android多国语言的value文件夹命名方式
    C++编程经验-返回局部变量的讨论(转)
  • 原文地址:https://www.cnblogs.com/water-radish/p/9280669.html
Copyright © 2011-2022 走看看