zoukankan      html  css  js  c++  java
  • POJ 2112 /// 最大流+floyd+二分

    题目大意:

    有 k台挤奶机 和 c头奶牛

    每台挤奶机最多为m头奶牛服务

    给定所有挤奶机和奶牛两两之间的距离

    求一种分配 使得 奶牛与挤奶机之间的最远距离 最小化

    floyd求得所有挤奶机与奶牛两两之间的最短距离

    二分一个最远距离M 建图

    超级源点s与所有奶牛连容量为1的边

    所有挤奶机与超级汇点t连容量为m的边

    奶牛与挤奶机之间距离<=M的连容量为1的边

    跑s到t的最大流 若最大流为c 说明这个最远距离M是符合要求的

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    using namespace std;
    #define LL long long 
    #define INF 0x3f3f3f3f
    #define mem(i,j) memset(i,j,sizeof(i))
    const int N=300;
    int d[N][N],L,R;
    int n,m,s,t;
    
    /**Dinic*/
    struct NODE { int v,w,r; };
    vector <NODE> E[N];
    void addE(int u,int v,int w) {
        E[u].push_back({v,w,E[v].size()});
        E[v].push_back({u,0,E[u].size()-1});
    }
    int lev[N], cur[N];
    bool bfs(int s,int t) {
        mem(lev,0); lev[s]=1; 
        queue <int> q; q.push(s);
        while(!q.empty()) {
            int u=q.front(); q.pop();
            for(int i=0;i<E[u].size();i++) {
                NODE e=E[u][i];
                if(e.w>0 && !lev[e.v]) {
                    lev[e.v]=lev[u]+1;
                    q.push(e.v);
                }
            }
        }
        return lev[t]>0;
    }
    int dfs(int s,int t,int f) {
        if(s==t) return f;
        for(int& i=cur[s];i<E[s].size();i++) {
            NODE& e=E[s][i];
            if(e.w>0 && lev[s]<lev[e.v]) {
                int d=dfs(e.v,t,min(f,e.w));
                if(d>0) {
                    e.w-=d; E[e.v][e.r].w+=d;
                    return d;
                }
            }
        }
        return 0;
    }
    int maxFlow(int s,int t) {
        int flow=0, f;
        while(bfs(s,t)) {
            mem(cur,0);
            while((f=dfs(s,t,INF))>0) flow+=f;
        }
        return flow;
    }
    /***/
    
    bool check(int k,int c,int m,int M) {
        for(int i=0;i<=n+1;i++) E[i].clear();
        s=0,t=n+1;
        for(int i=k+1;i<=n;i++) addE(s,i,1);
        for(int i=1;i<=k;i++) addE(i,t,m);
        for(int i=k+1;i<=n;i++)
            for(int j=1;j<=k;j++)
                if(d[i][j]<=M) addE(i,j,1);
        return maxFlow(s,t)==c;
    }
    
    void floyd(int k,int c) {
        L=INF, R=-INF;
        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]);
                    L=min(L,d[i][j]); R=max(R,d[i][j]);
                }
    }
    
    int main()
    {
        int k,c,m; 
        while(~scanf("%d%d%d",&k,&c,&m)) { 
            n=k+c;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++) {
                    scanf("%d",&d[i][j]);
                    if(i!=j && !d[i][j])
                        d[i][j]=INF;
                } 
            floyd(k,c); 
            int ans=0;
            while(L<=R) {
                int M=(L+R)>>1;
                if(check(k,c,m,M)) 
                    ans=M,R=M-1;
                else L=M+1;
            }
            printf("%d
    ",ans); 
        }
        
        return 0;
    }
    View Code
  • 相关阅读:
    Switch开关按钮控件----------WinForm控件开发系列
    图片旋转播放控件----------WinForm控件开发系列
    谷歌密码查看器
    Tarjan求LCA
    [题解]Hankson的趣味题
    [NOI Online]文具订购
    二分图判定
    hash表
    KMP算法
    拓扑排序入门
  • 原文地址:https://www.cnblogs.com/zquzjx/p/10663910.html
Copyright © 2011-2022 走看看