zoukankan      html  css  js  c++  java
  • poj3469 最小割

    最大流之后S集合与T集合不在相连,即s不能到达T中的点。 

    对于同一个模块,Ai,Bi,Ai与源点相连,Bi与汇点相连。不同CPU间消耗的模块,相连。

    由于最后模块只能在一个CPU中运行,所以要么与源点相连,要么与汇点相连,所以可看做最小割模型。

    我原来的Dinic模板,不是多路增广,所以超时。然后向大神学习了一下,就用现在这个模板,快很多很多。

    即是用一次增广代替了多次增广,到一个节点时就一次性地把与其相邻的所有边翻出来求增广的和,如果和为零,代表它已增广不出什么了,把这个点废掉即可。

    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #define maxn 20010
    #define Emaxn 201000
    #define INF 99999999
    using namespace std;
    struct node
    {
        int to;
        int v;
        int flag;
        int next;
    }edge[(Emaxn+maxn)*4];
    int pre[maxn],vis[maxn],index,n;
    void add(int x,int y,int z)
    {
        edge[index].to=y;
        edge[index].v=z;
        edge[index].flag=index+1;
        edge[index].next=pre[x];
        pre[x]=index++;
        edge[index].to=x;
        edge[index].v=0;
        edge[index].flag=index-1;
        edge[index].next=pre[y];
        pre[y]=index++;
    }
    void init()
    {
        index=1;
        memset(pre,-1,sizeof(pre));
    }
    int dfs(int u,int low)//此处增加used值表示当前使用了多少
    {
        int i,used=0;
        if(u==n+1)
            return low;
        for(i=pre[u];i!=-1&&used<low;i=edge[i].next)
        {
            if(vis[edge[i].to]==vis[u]+1&&edge[i].v)
            {
                int a=dfs(edge[i].to,min(low-used,edge[i].v));
                edge[i].v-=a;
                edge[edge[i].flag].v+=a;
                used+=a;
                //原来此处返回导致不停增广,而现在更具used值多次增广,知道无法增广为止,节省很多时间。
            }
        }
        if(!used)//如果当前的路不能增广了,该点就不需要被访问。
            vis[u]=-1;
        return used;
    }
    int BFS()
    {
        int i;
        queue<int>q;
        memset(vis,-1,sizeof(vis));
        vis[0]=0;
        q.push(0);
        while(!q.empty())
        {
            int t=q.front();
            q.pop();
            for(i=pre[t];i!=-1;i=edge[i].next)
            {
                if(vis[edge[i].to]<0&&edge[i].v>0)
                {
                    vis[edge[i].to]=vis[t]+1;
                    q.push(edge[i].to);
                }
            }
        }
        if(vis[n+1]>0)return 1;
        return 0;
    }
    int main()
    {
        int i,m;
        while(~scanf("%d%d",&n,&m))
        {
            init();
            for(i=1;i<=n;i++)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                add(0,i,x);
                add(i,n+1,y);
            }
            for(i=0;i<m;i++)
            {
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                add(x,y,z);
                add(y,x,z);
            }
            int ans=0;
            while(BFS())
            {
                while(1)
                {
                    int a=dfs(0,INF);
                    if(!a)break;
                    ans+=a;
                }
            }
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    java异常
    Map集和
    获取每个字符出现的次数
    从1-33号球中选取6个红球,且红球数字最多重复不超过3个 从1-16号球中选取一个篮球 由红球和蓝球共同组成一个双色球号码,且红球在左边(按照升序排列),篮球在右边。
    gitlab介绍及使用
    Maven使用介绍
    IDEA集成开发环境安装git,修改代码后文件变色代表的含义
    大数据相关
    开源镜像站汇总
    MySQL配置文件详解
  • 原文地址:https://www.cnblogs.com/sweat123/p/4869506.html
Copyright © 2011-2022 走看看