zoukankan      html  css  js  c++  java
  • hdu 3189(网络流+二分枚举)

    Steady Cow Assignment
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 6422   Accepted: 2202

    Description

    Farmer John's N (1 <= N <= 1000) cows each reside in one of B (1 <= B <= 20) barns which, of course, have limited capacity. Some cows really like their current barn, and some are not so happy.

    FJ would like to rearrange the cows such that the cows are as equally happy as possible, even if that means all the cows hate their assigned barn.

    Each cow gives FJ the order in which she prefers the barns. A cow's happiness with a particular assignment is her ranking of her barn. Your job is to find an assignment of cows to barns such that no barn's capacity is exceeded and the size of the range (i.e., one more than the positive difference between the the highest-ranked barn chosen and that lowest-ranked barn chosen) of barn rankings the cows give their assigned barns is as small as possible.

    Input

    Line 1: Two space-separated integers, N and B

    Lines 2..N+1: Each line contains B space-separated integers which are exactly 1..B sorted into some order. The first integer on line i+1 is the number of the cow i's top-choice barn, the second integer on that line is the number of the i'th cow's second-choice barn, and so on.

    Line N+2: B space-separated integers, respectively the capacity of the first barn, then the capacity of the second, and so on. The sum of these numbers is guaranteed to be at least N.

    Output

    Line 1: One integer, the size of the minumum range of barn rankings the cows give their assigned barns, including the endpoints.

    Sample Input

    6 4
    1 2 3 4
    2 3 1 4
    4 2 3 1
    3 1 2 4
    1 3 4 2
    1 4 2 3
    2 1 3 2

    Sample Output

    2

    Hint

    Explanation of the sample:

    Each cow can be assigned to her first or second choice: barn 1 gets cows 1 and 5, barn 2 gets cow 2, barn 3 gets cow 4, and barn 4 gets cows 3 and 6.
     
    这个题看懂题目才是关键啊。。。错了n多次.
    题意:有n头牛b个牛栏,每头牛对每个牛栏有一个满意度,每个牛栏有一个容量,输入n,b 然后输入的矩阵(i,j)代表的是第i头牛第j满意的是牛栏是 g[i][j] 。。就是这句话要看懂,然后最大满意度与最小满意度差值最小是多少(注意此处差值 = MAX-MIN+1).
    题解:看懂题后就容易了,构图的话就是建立超级源点S,S向每个牛栏建容量为牛栏容量的单向边,每头牛向超级汇点T连一条容量为1的边,然后枚举差值,当差值为刚好让最大流为n的时候就得到了满足条件的最小差值。
    #include <stdio.h>
    #include <algorithm>
    #include <queue>
    #include <string.h>
    #include <math.h>
    #include <iostream>
    #include <math.h>
    using namespace std;
    const int N = 1100;
    const int INF = 999999999;
    struct Edge{
        int v,next;
        int w;
    }edge[N*N];
    struct Cow{
        int love[25];
    }cow[N];
    int head[N];
    int level[N];
    int graph[N][N],dis[N][N],cap[N];
    int tot;
    void init(){
        memset(head,-1,sizeof(head));
        tot=0;
    }
    void addEdge(int u,int v,int w,int &k){
        edge[k].v = v,edge[k].w=w,edge[k].next=head[u],head[u]=k++;
        edge[k].v = u,edge[k].w=0,edge[k].next=head[v],head[v]=k++;
    }
    int BFS(int src,int des){
        queue<int >q;
        memset(level,0,sizeof(level));
        level[src]=1;
        q.push(src);
        while(!q.empty()){
            int u = q.front();
            q.pop();
            if(u==des) return 1;
            for(int k = head[u];k!=-1;k=edge[k].next){
                int v = edge[k].v;
                int w = edge[k].w;
                if(level[v]==0&&w!=0){
                    level[v]=level[u]+1;
                    q.push(v);
                }
            }
        }
        return -1;
    }
    int dfs(int u,int des,int increaseRoad){
        if(u==des) return increaseRoad;
        int ret=0;
        for(int k=head[u];k!=-1;k=edge[k].next){
            int v = edge[k].v;
            int w = edge[k].w;
            if(level[v]==level[u]+1&&w!=0){
                int MIN = min(increaseRoad-ret,w);
                w = dfs(v,des,MIN);
                if(w>0){
                edge[k].w -=w;
                edge[k^1].w+=w;
                ret+=w;
                if(ret==increaseRoad) return ret;
                }else level[v] = -1;
            }
        }
        return ret;
    }
    int Dinic(int src,int des){
        int ans = 0;
        while(BFS(src,des)!=-1) ans+=dfs(src,des,INF);
        return ans;
    }
    int n,b,src,des;
    int build(int t,int mid){
        init();
        for(int i=1;i<=b;i++){
            addEdge(src,i,cap[i],tot);
        }
        for(int i=1;i<=n;i++){
            addEdge(i+b,des,1,tot);
        }
        for(int i=t;i<=t+mid-1&&i<=b;i++){
            for(int j=1;j<=n;j++){
                addEdge(cow[j].love[i],j+b,1,tot);
            }
        }
        return Dinic(src,des);
    }
    int main(){
        scanf("%d%d",&n,&b);
        src = 0,des = n+b+1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=b;j++){
                scanf("%d",&cow[i].love[j]);
            }
        }
        for(int i=1;i<=b;i++) scanf("%d",&cap[i]);
        int l =0,r = b;
        int ans = b;
        while(l<=r){
            int mid = (l+r)>>1;  ///差值
            bool flag = false;
            for(int i=1;i<=b;i++){ ///枚举最小值
                if(build(i,mid)==n) {
                    flag = 1;
                    break;
                }
            }
            if(flag) {
                ans = mid;
                r = mid-1;
            }else l = mid+1;
        }
        printf("%d
    ",ans);
    }
  • 相关阅读:
    安卓学习第12课——SimpleAdapter
    用栈结构实现多项式计算器
    用B-树实现虚拟图书管理系统
    HDU4791【杂】
    HDU4801【DFS】
    萌新学习图的强连通(Tarjan算法)笔记
    Lightoj 1021【状压DP(未搞)】
    Lightoj 1008【规律】
    CodeForces Canada Cup 2016【A,B,C,D】
    51nod 1068【简单博弈】
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5557376.html
Copyright © 2011-2022 走看看