POJ 3189--Steady Cow Assignment【二分图多重匹配 && 最大流求解 && 枚举 && 经典】

Steady Cow Assignment

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 6023   Accepted: 2078

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

题意:

有n头牛,m个牛棚,每个牛棚都有一定的容量(就是最多能装多少只牛),然后每只牛对每个牛圈的喜好度不同(就是所有牛圈在每个牛心中都有一个排名),然后要求所有的牛都进猪圈,牛棚在牛心中的排名差计算方法为:所有牛中最大排名和最小排名之差。问最小的排名差。

英语不好太坑了 ,理解错了题意,以测试数据举例:

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

前6行是每头牛对牛棚的排名, 第二行2  3  1  4 代表的是 对第二头牛而言,第二个牛棚排第一,第三个牛棚排第二,第一个牛棚排第三,第四个牛棚排第四。

不是第一个牛棚排第二,第二个牛棚排第三,第三个牛棚排第一,第四个牛棚排第四。这点理解搓个 ,wa了好多遍,英语不好真是要哭了。

解析:这一题其实不难,数据比较小,可以用最大流来写,建图有点麻烦,下面是建图过程:

(1)首先虚拟一个源点,汇点。

(2)源点向每头牛建边, 权值为1,

(3)牛棚向汇点建边,权值为每个牛棚的容量。

(4)枚举牛棚的最差排名和最好排名(即枚举排名差) ,在这个排名之内牛和这个牛棚建边。

看看每种情况判断是否合法(是否满流),取最小值。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define maxn 1200
#define maxm 100005
#define INF 0x3f3f3f3f
using namespace std;
int n, m;

struct node {
    int u, v, cap, flow, next;
};
node edge[maxm];
int head[maxn], cnt;
int cur[maxn];
int dist[maxn], vis[maxn];
int num[maxn];//每个牛棚的容量
int val[1200][25];

void init(){
    cnt = 0;
    memset(head, -1, sizeof(head));
}

void add(int u, int v, int w){
    node E;
    edge[cnt] = {u, v, w, 0, head[u]};
    head[u] = cnt++;
    edge[cnt] = {v, u, 0, 0 ,head[v]};
    head[v] = cnt++;
}

void input(){
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
            scanf("%d", &val[i][j]);
    for(int i = 1; i <= m; ++i){
        scanf("%d", &num[i]);
    }
}

void getmap(int l, int r){
    for(int i = 1; i <= n; ++i)
        add(0, i, 1);
    for(int j = 1; j <= m; ++j)
        add(n + j, n + m + 1, num[j]);
//    for(int i = 1; i <= n; ++i)
//        for(int j = 1; j <= m; ++j)
//        if(val[i][j] >= l && val[i][j] <= r)
//        add(i, j + n, 1);
    for(int i = 1; i <= n; ++i)
        for(int j = l; j <= r; ++j)
        add(i, val[i][j] + n, 1);
}

bool BFS(int st ,int ed){
    queue<int>q;
    memset(vis, 0 ,sizeof(vis));
    memset(dist, -1, sizeof(dist));
    vis[st] = 1;
    dist[st] = 0;
    q.push(st);
    while(!q.empty()){
        int u = q.front();
        q.pop();
        for(int i = head[u]; i != -1; i = edge[i].next){
            node E = edge[i];
            if(!vis[E.v] && E.cap > E.flow){
                vis[E.v] = 1;
                dist[E.v] = dist[u] + 1;
                if(E.v == ed)
                    return true;
                q.push(E.v);
            }
        }
    }
    return false;
}

int DFS(int x, int ed, int a){
    if(x == ed || a == 0)
        return a;
    int flow = 0, f;
    for(int &i = cur[x]; i != -1; i = edge[i].next){
        node &E = edge[i];
        if(dist[E.v] == dist[x] + 1 && (f = DFS(E.v, ed, min(a, E.cap - E.flow))) > 0){
            E.flow += f;
            edge[i ^ 1].flow -= f;
            a -= f;
            flow += f;
            if(a == 0)
                break;
        }
    }
    return flow;
}

int maxflow(int st, int ed){
    int flowsum = 0;
    while(BFS(st,ed)){
        memcpy(cur, head, sizeof(head));
        flowsum += DFS(st, ed, INF);
    }
    return flowsum;
}

int main(){
    while(scanf("%d%d", &n, &m) != EOF){
        input();
        int ans = INF;
        for(int i = 1; i <= m; ++i){//枚举排名的下界
            for(int j = i; j <= m; ++j){//枚举排名的上界
                init();
                getmap(i, j);
                if(maxflow(0, n + m + 1) == n)
                    ans = min(ans, j - i + 1);
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-29 08:59:56

POJ 3189--Steady Cow Assignment【二分图多重匹配 && 最大流求解 && 枚举 && 经典】的相关文章

POJ3189 Steady Cow Assignment —— 二分图多重匹配/最大流 + 二分

题目链接:https://vjudge.net/problem/POJ-3189 Steady Cow Assignment Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6979   Accepted: 2418 Description Farmer John's N (1 <= N <= 1000) cows each reside in one of B (1 <= B <= 20) barns wh

Poj 3189 Steady Cow Assignment (多重匹配)

题目链接: Poj 3189 Steady Cow Assignment 题目描述: 有n头奶牛,m个棚,每个奶牛对每个棚都有一个喜爱程度.当然啦,棚子也是有脾气的,并不是奶牛想住进来就住进来,超出棚子的最大容量了,棚子是拒绝的.现在要给每个奶牛安家,本宝宝是一个公正无私的人类,所以要找一个奶牛喜爱程度差值最小的方案(虽然这样大家的喜爱程度可能普遍偏低,因为绝对公平并不代表合理啊),问喜爱程度的区间最小为多大? 解题思路: 每个棚子并不是住一个奶牛,所以是多重匹配咯.匹配的时候二分枚举喜爱程度的

POJ 3189 Steady Cow Assignment(最大流)

POJ 3189 Steady Cow Assignment 题目链接 题意:一些牛,每个牛心目中都有一个牛棚排名,然后给定每个牛棚容量,要求分配这些牛给牛棚,使得所有牛对牛棚的排名差距尽量小 思路:这种题的标准解法都是二分一个差值,枚举下界确定上界,然后建图判断,这题就利用最大流进行判断,值得一提的是dinic的效率加了减枝还是是卡着时间过的,这题理论上用sap或者二分图多重匹配会更好 代码: #include <cstdio> #include <cstring> #inclu

POJ3189_Steady Cow Assignment(二分图多重匹配/网络流)

解题报告 http://blog.csdn.net/juncoder/article/details/38340447 题目传送门 题意: B个猪圈,N头猪,每头猪对每个猪圈有一个满意值,要求安排这些猪使得最大满意和最小满意的猪差值最小 思路: 二分图的多重匹配问题; 猪圈和源点连边,容量为猪圈容量,猪与汇点连边,容量1; 猪圈和猪之间连线取决所取的满意值范围; 二分查找满意值最小差值的范围. #include <iostream> #include <cstring> #incl

POJ 3189 Steady Cow Assignment(网络流之最大流+二分构图)

题目地址:POJ 3189 我晕啊...飞快的把白天的任务完成又有什么用...节省下来的时间活生生的被我的手残给全浪费掉了...又调了一整天,问题居然是一个地方的n和m写反了!!!反思..反思...面壁去... 这题就是二分区间,然后枚举区间位置.然后建图就行了.不多说.. 代码如下: #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include

POJ3189_Steady Cow Assignment(二分图多重匹配/网络流+二分构图)

解题报告 http://blog.csdn.net/juncoder/article/details/38340447 题目传送门 题意: B个猪圈,N头猪.每头猪对每一个猪圈有一个惬意值.要求安排这些猪使得最大惬意和最小惬意的猪差值最小 思路: 二分图的多重匹配问题; 猪圈和源点连边,容量为猪圈容量.猪与汇点连边,容量1; 猪圈和猪之间连线取决所取的惬意值范围; 二分查找惬意值最小差值的范围. #include <iostream> #include <cstring> #inc

poj 3189 Steady Cow Assignment 【最大流】【枚举上下界 判断是否满流】

Steady Cow Assignment Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6029   Accepted: 2083 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. So

POJ 3189 Steady Cow Assignment

题意:每个奶牛对所有的牛棚有个排名(根据喜欢程度排的),每个牛棚能够入住的牛的数量有个上限,重新给牛分配牛棚,使牛棚在牛心中的排名差(所有牛中最大排名和最小排名之差)最小. 题目输入: 首先是两个数字N , B代表有N只牛B个牛棚 接下来的第一行B个数字代表每个牛棚最多能容纳多少牛. 接下来N行每行B个数字代表牛心中牛棚的排名. 我勒个去啊!真郁闷,WA了好多次终于AC发现自己错是因为重新构图后下标是从0开始的,改成下标从 1 开始的就AC了 #include<stdio.h> #includ

poj 1698 Alice&#39;s Chance 二分图多重匹配

题意: 一个演员要拍n部电影,每部电影只能在一周的特定几天拍(如周2,周4,周5),第i部电影要拍di天,必须要在wi周拍完,问演员是否可以完成任务. 分析: 建二分图,转化为二分图的多重匹配. 代码: //poj 1698 //sep9 #include <iostream> using namespace std; const int maxX=64*7; const int maxY=64; int g[maxX][maxY],match[maxY][maxX]; int vis[max