zoukankan      html  css  js  c++  java
  • poj2112 最大流

    我用Dinic写的。G++ 1800ms 很慢,c++直接超时。优化后的 141ms,很快!

    对于此题,建图方法很巧妙,通常想到求距离,那就会朝距离的方向建图,但是这题根据牛个数来建图,然后二分距离。

      先求出任意点之间的最短距离。对于挤奶器,牛,很明显的分为2部分。挤奶器的牛来自牛这部分。先另外设源点和汇点。对于牛部分,都与源点相连,容量为1。然后二分

    距离,对于挤奶器和牛之间的容量,如果挤奶器和牛之间的距离小于或等于二分的距离,那么此路可以通过牛。然后挤奶器与汇点之间的容量为m值。这样图就建完了。然后Dinic

    求最大流(此时最大流的值表示牛的个数),如果此时最大流的值>=c,即满足牛的个数,那这个距离是可以的,然后继续二分,知道得到结果。

    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #define maxn 300
    #define INF 99999999
    using namespace std;
    int map[maxn][maxn],dis[maxn][maxn],vis[maxn];
    int k,c,m;
    int min(int x,int y)
    {
        return x<y?x:y;
    }
    void floyd(int n)
    {
        int i,j,t;
        for(t=1;t<=n;t++)
        {
            for(i=1;i<=n;i++)
            {
                for(j=1;j<=n;j++)
                {
                    if(dis[i][j]>dis[i][t]+dis[t][j])
                        dis[i][j]=dis[i][t]+dis[t][j];
                }
            }
        }
    }
    void makemap(int maxval,int n)
    {
        int i,j;
        memset(map,0,sizeof(map));
        for(i=1;i<=k;i++)
            map[i][n+1]=m;
        for(i=k+1;i<=n;i++)
            map[0][i]=1;
        for(i=k+1;i<=n;i++)
        {
            for(j=1;j<=k;j++)
            {
                if(dis[i][j]<=maxval)
                    map[i][j]=1;
            }
        }
    }
    int BFS(int n)
    {
        int i,j;
        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=0;i<=n+1;i++)
            {
                if(vis[i]<0&&map[t][i])
                {
                    q.push(i);
                    vis[i]=vis[t]+1;
                }
            }
        }
        if(vis[n+1]>0)
            return 1;
        return 0;
    }
    int dfs(int u,int low,int n)
    {
        int i,j,a;
        if(u==n)
            return low;
        for(i=0;i<=n;i++)
        {
            if(vis[i]==vis[u]+1&&map[u][i])
            {
                a=dfs(i,min(low,map[u][i]),n);
                if(!a)continue;
                map[u][i]-=a;
                map[i][u]+=a;
                return a;
            }
        }
        return 0;
    }
    int main()
    {
        int i,j,n;
        while(scanf("%d%d%d",&k,&c,&m)!=EOF)
        {
            n=k+c;
            for(i=1;i<=k+c;i++)
            {
                for(j=1;j<=k+c;j++)
                {
                    scanf("%d",&dis[i][j]);
                    if(dis[i][j]==0)//不连通给予无穷,防止floyd出现问题
                        dis[i][j]=INF;
                }
            }
            floyd(n);
    
            /*for(i=1;i<=k+c;i++)
            {
                for(j=1;j<=k+c;j++)
                {
                    printf("%d ",dis[i][j]);
                }
                printf("
    ");
            }*/
    
            int L=0,R=40000;
            int ans=0;
            int rt=0;
            while(L<=R)//二分答案
            {
                rt=0;
                int mid=(L+R)/2;
                makemap(mid,n);//根据二分的值建图
                while(BFS(n))
                {
                    int fa=dfs(0,INF,n+1);
                    if(!fa) break;;
                    rt+=fa;
                }
                if(rt>=c)
                {
                    R=mid-1;
                    ans=mid;
                }
                else 
                {
                    L=mid+1;
                }
            }
            printf("%d
    ",ans);
        }
    }

    优化后:

    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #define maxn 300
    #define INF 99999999
    using namespace std;
    int map[maxn][maxn],dis[maxn][maxn],vis[maxn];
    int k,c,m;
    int min(int x,int y)
    {
        return x<y?x:y;
    }
    void floyd(int n)
    {
        int i,j,t;
        for(t=1;t<=n;t++)
        {
            for(i=1;i<=n;i++)
            {
                for(j=1;j<=n;j++)
                {
                    if(dis[i][j]>dis[i][t]+dis[t][j])
                        dis[i][j]=dis[i][t]+dis[t][j];
                }
            }
        }
    }
    void makemap(int maxval,int n)
    {
        int i,j;
        memset(map,0,sizeof(map));
        for(i=1;i<=k;i++)
            map[i][n+1]=m;
        for(i=k+1;i<=n;i++)
            map[0][i]=1;
        for(i=k+1;i<=n;i++)
        {
            for(j=1;j<=k;j++)
            {
                if(dis[i][j]<=maxval)
                    map[i][j]=1;
            }
        }
    }
    int BFS(int n)
    {
        int i,j;
        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=0;i<=n+1;i++)
            {
                if(vis[i]<0&&map[t][i])
                {
                    q.push(i);
                    vis[i]=vis[t]+1;
                }
            }
        }
        if(vis[n+1]>0)
            return 1;
        return 0;
    }
    int dfs(int u,int low,int n)
    {
        int i,j,a,used=0;
        if(u==n)
            return low;
        for(i=0;i<=n&&used<low;i++)
        {
            if(vis[i]==vis[u]+1&&map[u][i])
            {
                a=dfs(i,min(low-used,map[u][i]),n);//多路增广
                if(!a)continue;
                map[u][i]-=a;
                map[i][u]+=a;
                used+=a;
            }
        }
        if(!used)
            vis[u]=-1;
        return used;
    }
    int main()
    {
        int i,j,n;
        while(scanf("%d%d%d",&k,&c,&m)!=EOF)
        {
            n=k+c;
            for(i=1;i<=k+c;i++)
            {
                for(j=1;j<=k+c;j++)
                {
                    scanf("%d",&dis[i][j]);
                    if(dis[i][j]==0)//不连通给予无穷,防止floyd出现问题
                        dis[i][j]=INF;
                }
            }
            floyd(n);
    
            /*for(i=1;i<=k+c;i++)
            {
                for(j=1;j<=k+c;j++)
                {
                    printf("%d ",dis[i][j]);
                }
                printf("
    ");
            }*/
    
            int L=0,R=40000;
            int ans=0;
            int rt=0;
            while(L<=R)//二分答案
            {
                rt=0;
                int mid=(L+R)/2;
                makemap(mid,n);//根据二分的值建图
                while(BFS(n))
                {
                    int fa=dfs(0,INF,n+1);
                    if(!fa) break;;
                    rt+=fa;
                }
                if(rt>=c)
                {
                    R=mid-1;
                    ans=mid;
                }
                else
                {
                    L=mid+1;
                }
            }
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    vi 批量加注释与替换
    linux常用快捷键
    kubectl常用命令
    软件管理方法
    zabbix3.2升级3.4报错Database error
    zabbix显示中文乱码
    主从复制延迟及原因
    Python-- 文件与操作系统
    层次聚类
    盲源分离
  • 原文地址:https://www.cnblogs.com/sweat123/p/4833944.html
Copyright © 2011-2022 走看看