zoukankan      html  css  js  c++  java
  • poj Optimal Milking

                                                         Optimal Milking

     

    题目:

       有K个机器。C仅仅牛。要求求出最全部牛到各个产奶机的最短距离。给出一个C+K的矩阵,表示各种标号间的距离。

    而每一个地方最多有M仅仅牛。

     

    算法分析:

       二分+最短路+网络流

    想法难以想到。我是看解题报告的思路。

    然后。自己上了手。開始wrong 了3次。后来各种该。无意的一个更改就AC了。无语勒。

    。。。

    wrong 在了,网络流建图的时候仅仅能是机器和奶牛之间的距离关系。而奶牛跟奶牛或者机器跟机器不要建边。当时脑残了。!。!


    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int INF = 1 << 20;
    const int MAXN = 1000;
    
    struct Edge{
       int from,to,cap,flow,cost;
       Edge(){};
       Edge(int _from,int _to,int _cap,int _flow)
           :from(_from),to(_to),cap(_cap),flow(_flow){};
    };
    vector<Edge> edges;
    vector<int> G[MAXN];
    int cur[MAXN],d[MAXN];
    bool vst[MAXN];
    int src,sink;
    int dist[MAXN][MAXN];
    int K,C,M,V;
    
    void init(){
        src = V + 1; sink = src + 1;
        for(int i = 0;i <= sink;++i)
            G[i].clear();
        edges.clear();
    }
    
    void flody(){
        for(int k = 0;k < V;++k)
         for(int i = 0;i < V;++i)
           for(int j = 0;j < V;++j)
             if(dist[i][j] > dist[i][k] + dist[k][j])
               dist[i][j] = dist[i][k] + dist[k][j];
    //    for(int i = 0;i < V;++i){
    //        for(int j = 0;j < V;++j)
    //           printf("%d ",dist[i][j]);
    //        puts("");
    //    }
    }
    
    void addEdge(int from,int to,int cap){
        edges.push_back(Edge(from,to,cap,0));
        edges.push_back(Edge(to,from,0,0));
        int sz = edges.size();
        G[from].push_back(sz - 2);
        G[to].push_back(sz - 1);
    }
    
    void build(int limit){
        init();
    
        for(int i = K;i < V;++i){  // 奶牛与源点
            addEdge(src,i,1);
        }
    
        for(int i = 0;i < K;++i){ //机器与汇点
            addEdge(i,sink,M);
        }
       
       //注意---> i = K!!! j < K!!!!
        for(int i = K;i < V;++i){  //奶牛与机器的连接
            for(int j = 0;j < K;++j){
                if(dist[i][j] <= limit){
                    addEdge(i,j,1);
                }
            }
        }
    
    }
    
    bool BFS(){
        memset(vst,0,sizeof(vst));
        queue<int> Q;
        Q.push(src);
        d[src] = 0;
        vst[src] = 1;
    
        while(!Q.empty()){
            int x = Q.front(); Q.pop();
            for(int i = 0;i < (int)G[x].size();++i){
                Edge& e = edges[G[x][i]];
                if(!vst[e.to] && e.cap > e.flow){
                    vst[e.to] = 1;
                    d[e.to] = d[x] + 1;
                    Q.push(e.to);
                }
            }
        }
    
        return vst[sink];
    }
    
    int DFS(int x,int a){
        if(x == sink||a == 0)
            return a;
    
        int flow = 0,f;
        for(int& i = cur[x];i < (int)G[x].size();++i){
            Edge& e = edges[G[x][i]];
            if(d[e.to] == d[x] + 1&&(f = DFS(e.to,min(a,e.cap - e.flow))) > 0){
                e.flow += f;
                edges[G[x][i]^1].flow -= f;
                flow += f;
                a -= f;
                if(a == 0) break;
            }
        }
        return flow;
    }
    
    int maxFlow(){
        int flow = 0;
        while(BFS()){
            memset(cur,0,sizeof(cur));
            flow += DFS(src,INF);
        }
        return flow;
    }
    
    bool Check(int mid){
        build(mid);
        int flow = maxFlow();       //cout << "flow : " << flow << endl;
    
        return flow == C;
    }
    
    void solve(){
        flody();
    
        int lb = -1,ub = INF + 100;
        while(ub - lb > 1){
            int mid = (lb + ub) / 2;
            if(Check(mid))
                ub = mid;
            else
                lb = mid;
    
           //cout << "mid: " << mid << " lb: " << lb << "  ub: " << ub << endl;
        }
    
        printf("%d
    ",ub);
    }
    
    int main()
    {
      //  freopen("Input.txt","r",stdin);
    
        while(~scanf("%d%d%d",&K,&C,&M)){
            V = K + C;
            int x;
            for(int i = 0;i < V;++i){
                for(int j = 0;j < V;++j){
                    scanf("%d",&x);
                    dist[i][j] = (x == 0 ? INF : x);
                }
                dist[i][i] = 0;
            }
    
            solve();
        }
        return 0;
    }
    
    


     

    另一种是多个匹配,。没有写。成品填充。

    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    全能VIP音乐在线解析
    wordpress插件推荐
    day 34 IO模型
    day 33 协程、 socketserver模块
    day 32-2 练习
    day 32-2 并发编程——认识线程(下)
    day 32 练习
    day 32 并发编程——认识线程(上)
    day 31-1 练习
    day 31-1 守护进程、互斥锁、队列、生产消费模型
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4878755.html
Copyright © 2011-2022 走看看