zoukankan      html  css  js  c++  java
  • P3376 【模板】网络最大流

     P3376 【模板】网络最大流

    题目描述

    如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。

    输入输出格式

    输入格式:

    第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。

    接下来M行每行包含三个正整数ui、vi、wi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi)

    输出格式:

    一行,包含一个正整数,即为该网络的最大流。

    输入输出样例

    输入样例#1:
    4 5 4 3
    4 2 30
    4 3 20
    2 3 20
    2 1 30
    1 3 40
    输出样例#1:
    50

    说明

    时空限制:1000ms,128M

    数据规模:

    对于30%的数据:N<=10,M<=25

    对于70%的数据:N<=200,M<=1000

    对于100%的数据:N<=10000,M<=100000

    样例说明:

    题目中存在3条路径:

    4-->2-->3,该路线可通过20的流量

    4-->3,可通过20的流量

    4-->2-->1-->3,可通过10的流量(边4-->2之前已经耗费了20的流量)

    故流量总计20+20+10=50。输出50。

    Dinic1

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define R register
    using namespace std;
    int read(){
        R int x=0;bool f=1;
        R char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=0;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    const int N=1e4+10;
    const int M=1e5+10;
    int n,m,S,T,head[N],cur[N],dis[N],q[N*2];
    bool vis[N];
    struct node{
        int v,next,cap,flow;
    }e[M<<1];int tot=1;
    void add(int x,int y,int z){
        e[++tot]=(node){y,head[x],z,0};head[x]=tot;
        e[++tot]=(node){x,head[y],0,0};head[y]=tot;
    }
    bool bfs(){
        int h=0,t=1;
        memset(dis,-1,sizeof(dis));
        dis[S]=0;q[1]=S;
        while(h!=t){
            int x=q[++h];
            for(int i=head[x];i;i=e[i].next){
                int v=e[i].v;
                if(dis[v]==-1&&e[i].cap>e[i].flow){//TLE*1 
                    dis[v]=dis[x]+1;
                    q[++t]=v;
                }
            }
        }
        return dis[T]!=-1;
    }
    int dfs(int x,int f){
        if(x==T||!f) return f;
        int used=0,f1;
        for(int &i=cur[x];i;i=e[i].next){
            if(dis[x]+1==dis[e[i].v]&&(f1=dfs(e[i].v,min(f,e[i].cap-e[i].flow)))>0){
                e[i].flow+=f1;e[i^1].flow-=f1;
                used+=f1;f-=f1;
                if(!f) break;
            }
        }
        return used;
    }
    int dinic(){
        int ans=0;
        while(bfs()){
            for(int i=1;i<=n;i++) cur[i]=head[i];
            ans+=dfs(S,0x7fffffff);
        }
        return ans;
    }
    int main(){
        n=read();m=read();S=read();T=read();
        for(int i=1,x,y,z;i<=m;i++){
            x=read();y=read();z=read();
            add(x,y,z);
        }
        printf("%d",dinic());
        return 0;
    }

    Dinic 2

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define R register
    #define inf 0x3f3f3f3f
    using namespace std;
    int read(){
        R int x=0;bool f=1;
        R char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=0;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    const int N=1e5+10;
    int S,T,n,m;
    int head[N],dis[N],q[N*2];
    struct node{
        int v,next,cap;
    }e[N<<2];int tot=1;
    void add(int x,int y,int z){
        e[++tot]=(node){y,head[x],z};head[x]=tot;
    }
    bool bfs(){
        int h=0,t=1;
        memset(dis,-1,sizeof(dis));
        dis[S]=0;q[1]=S;
        while(h!=t){
            int x=q[++h];
            for(int i=head[x];i;i=e[i].next){
                int v=e[i].v;
                if(dis[v]==-1&&e[i].cap){
                    dis[v]=dis[x]+1;
                    q[++t]=v;
                }
            }
        }
        return dis[T]!=-1;
    }
    int dfs(int now,int f){
        if(now==T) return f;
        int rest=f;
        for(int i=head[now];i;i=e[i].next){
            int v=e[i].v;
            if(e[i].cap&&dis[v]==dis[now]+1&&rest){
                int t=dfs(v,min(rest,e[i].cap));
                if(!t) dis[v]=0;
                e[i].cap-=t;
                e[i^1].cap+=t;
                rest-=t;
            }
        }
        return f-rest;
    }
    int dinic(){
        int ans=0;
        while(bfs()) ans+=dfs(S,inf);
        return ans;
    }
    int main(){
        scanf("%d%d%d%d",&n,&m,&S,&T);
        for(int i=1,x,y,z;i<=m;i++){
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);add(y,x,0);
        }
        printf("%d",dinic());
        return 0;
    }

    ISAP

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define R register
    using namespace std;
    int read(){
        R int x=0;bool f=1;
        R char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=0;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    const int N=1e4+10;
    const int M=1e5+10;
    int n,m,S,T,head[N],cur[N],par[N],gap[N],dis[N];
    bool vis[N];
    struct node{
        int u,v,next,cap,flow;
        node(int u=0,int v=0,int next=0,int cap=0,int flow=0){
            this->u=u;
            this->v=v;
            this->next=next;
            this->cap=cap;
            this->flow=flow;
        }
    }e[M<<1];int tot=1;
    void add(int x,int y,int z){
        e[++tot]=node(x,y,head[x],z,0);
        head[x]=tot;
    }
    void bfs(){
        queue<int>q;
        q.push(T);
        vis[T]=1;dis[T]=0;
        while(!q.empty()){
            int x=q.front();q.pop();
            for(int i=head[x];i;i=e[i].next){
                int v=e[i].v;
                if(!vis[v]&&!e[i].cap){
                    vis[v]=1;
                    dis[v]=dis[x]+1;
                    q.push(v); 
                }
            }
        }
    }
    int agument(){//更新残留网络
        int ans=0x7fffffff;
        for(int p=T;p!=S;p=e[par[p]].u) ans=min(ans,e[par[p]].cap-e[par[p]].flow);
        for(int p=T;p!=S;p=e[par[p]].u) e[par[p]].flow+=ans,e[par[p]^1].flow-=ans;
        return ans;    
    }
    int ISAP(){
        int ans=0;
        for(int i=1;i<=n;i++) gap[dis[i]]++,cur[i]=head[i];
        for(int p=S;dis[p]<n;){
            if(p==T){//达到终点就增广 
                ans+=agument();
                p=S;
            }
            bool ok=0;
            for(int i=cur[p];i;i=e[i].next){
                int v=e[i].v;//寻找当前找到的一条路径上的最大流
                if(dis[p]==dis[v]+1&&e[i].cap>e[i].flow){
                    ok=1;par[v]=i;cur[p]=i;p=v;
                    break;
                }
            }
            if(!ok){//找不到可行弧
                if(--gap[dis[p]]==0) break;//(更新gap数组)当前标号的数目减1 =>如果出现断层,则该点为一个唯一点,后退也没有意义
                int mn=n-1;//寻找与当前点相连接的点中最小的距离标号
                for(int i=head[p];i;i=e[i].next) if(e[i].cap>e[i].flow) mn=min(mn,dis[e[i].v]);
                gap[dis[p]=mn+1]++;
                cur[p]=head[p];
                if(p!=S) p=e[par[p]].u;//相当于后退一步
            }
        }
        return ans;
    }
    int main(){//初始化清零已省去 
        n=read();m=read();S=read();T=read();
        for(int i=1,x,y,z;i<=m;i++){
            x=read();y=read();z=read();
            add(x,y,z);
            add(y,x,0);
        }
        bfs();
        printf("%d",ISAP());
        return 0;
    }
  • 相关阅读:
    点云处理算法核心-八叉树
    点云平台之cloudCompare开发三
    点云法向量估计方法
    PCL源码编译
    PCL裁剪之多边形裁剪
    点云平台PCLvisualization多边形裁剪方法初探
    点云合并pcl重载“+”
    点云平台之CloudCompare开发二
    点云平台之QtitanRibbon
    神舟电脑 战神ZX6-CT5A2 键盘失灵
  • 原文地址:https://www.cnblogs.com/shenben/p/6236147.html
Copyright © 2011-2022 走看看