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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。