zoukankan      html  css  js  c++  java
  • poj2112 二分+floyd+最大流 好题

      这个题的意思是有K个挤奶机器, 和C个牛,一个机器每天最多服务W个奶牛,  如果将牛和机器看成顶点那么告诉两顶点之间的距离, 那么请最小化奶牛去挤奶的时候走的路的最大值, 首先我们可以使用floyd求出奶牛去某个挤奶机器的最短路径,然后二分一个答案, 建图, 我们再定义一个超级源点和超级汇点, 源点指向机器, 权值为W, 机器和奶牛之间也有边, 满足条件为边的长度小于等于二分的答案, 权值为1, 每个奶牛到汇点也有一个边权值为1, 求出此图的最大流观察其是否等于奶牛的数量, 代码如下:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <queue>
    
    using namespace std;
    int K, C, M;
    int d[250][250];
    
    const int maxn = 500;
    const int inf = 0x3f3f3f3f;
    
    struct Dinic
    {
        int n;       //n个顶点
        struct edge
        {
            int from, to, cap;
        };
        vector<int> G[maxn];
        vector<edge> e;
        int level[maxn], iter[maxn];
    
        void init()
        {
            for(int i=0; i<=n; i++) G[i].clear();
            e.clear();
        }
    
        void add_edge(int u, int v, int cap)
        {
            e.push_back((edge)
            {
                u, v, cap
            });
            e.push_back((edge)
            {
                v, u, 0
            });
            int m = e.size();
            G[u].push_back(m-2);
            G[v].push_back(m-1);
        }
    
        void bfs(int s)
        {
            memset(level, -1, sizeof(level));
            queue<int> que;
            level[s] = 0;
            que.push(s);
            while(!que.empty())
            {
                int u = que.front();
                que.pop();
                for(int i=0; i<G[u].size(); i++)
                {
                    edge &te = e[G[u][i]];
                    if(te.cap>0 && level[te.to]<0)
                    {
                        level[te.to] = level[u] + 1;
                        que.push(te.to);
                    }
                }
            }
        }
    
        int dfs(int v, int t, int f)
        {
            if(v == t) return f;
            for(int &i=iter[v]; i<G[v].size(); i++)
            {
                edge &tpe = e[G[v][i]];
                if(tpe.cap>0 && level[v]<level[tpe.to])
                {
                    int d = dfs(tpe.to, t, min(f, tpe.cap));
                    if(d > 0)
                    {
                        tpe.cap -= d;
                        e[G[v][i]^1].cap += d;
                        return d;
                    }
                }
            }
            return 0;
        }
    
        int max_flow(int s, int t)
        {
            int flow = 0;
            for(;;)
            {
                bfs(s);
                if(level[t]<0) return flow;
                memset(iter, 0, sizeof(iter));
                int f;
                while((f=dfs(s, t, 0x3fffffff)) > 0)
                    flow += f;
            }
        }
    } di;
    
    void floyd()
    {
        int n = K+C;
        for(int k=1; k<=n; k++)
        for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
            d[i][j] = min(d[i][j], d[i][k]+d[k][j]);
    }
    
    bool check(int mid)
    {
        di.n = K+C+2;   //0超级源点 machine 1-K cow K+1-K+C  K+C+1超级汇点
        di.init();
        for(int i=1; i<=K; i++)       //机器
        {
            for(int j=1+K; j<=C+K; j++)   if(d[i][j]<=mid) //奶牛
            {
                int u=i, v=j;
                di.add_edge(u, v, 1);
            }
            di.add_edge(0, i, M);
        }
        for(int j=1; j<=C; j++) di.add_edge(K+j, K+C+1, 1);
        int f = di.max_flow(0, K+C+1);
        return f==C;
    }
    
    int main()
    {
        while(scanf("%d%d%d", &K, &C, &M)==3)
        {
            for(int i=1; i<=K+C; i++)
                for(int j=1; j<=K+C; j++)
                {
                    scanf("%d", &d[i][j]);
                    if(i!=j && d[i][j]==0) d[i][j] = inf;
                }
            floyd();
            int l=0, r=100000;
            int ans;
    
            while(l <= r)
            {
                int mid = (l+r)/2;
                if(check(mid))
                {
                    ans = mid;
                    r = mid - 1;
                }
                else l = mid + 1;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    jsp 防止表单多次提交
    linux 部署java 项目命令
    checkbox 选中获取值
    java 实现用户自由选择字段实现导出EXCEL表格
    从七牛服务下载PDF文件
    【sping揭秘】9、容器内部事件发布(二)
    【sping揭秘】8、容器内部事件发布(一)
    【sping揭秘】7、国际化信息支持
    【sping揭秘】6、IOC容器之统一资源加载策略
    【sping揭秘】5、IOC容器(一)
  • 原文地址:https://www.cnblogs.com/xingxing1024/p/5244973.html
Copyright © 2011-2022 走看看