POJ3189 Steady Cow Assignment —— 二分圖多重匹配/最大流 + 二分
阿新 • • 發佈:2017-11-13
next cows int find ebr including top miss -s
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.
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.
Line 1: One integer, the size of the minumum range of barn rankings the cows give their assigned barns, including the endpoints.
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.
USACO 2006 February Gold
題目鏈接: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 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
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
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.
Source
題解:
題意:有n頭牛, 安排到m個牲棚裏住。每頭牛對每個牲棚都有一個好感度排名。主人為了使得這些牛盡可能滿意,規定了獲得最低好感度的牛和獲得最高好感度的牛的好感度差值最小(即好感度跨度最小)。
1.二分跨度。然後對於每個跨度,枚舉最低好感度(最高好感度也就可以求出),然後開始建圖:如果某頭牛對某個牲棚的好感度在這個範圍內,則連上邊;否則不連。
2.用二分圖多重匹配或者最大流,求出是否每頭牛都可以被安排到某個牲棚中。如果可以,則縮小跨度,否則增大跨度。
多重匹配:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <string> 6 #include <vector> 7 #include <map> 8 #include <set> 9 #include <queue> 10 #include <sstream> 11 #include <algorithm> 12 using namespace std; 13 const int INF = 2e9; 14 const int MOD = 1e9+7; 15 const int MAXM = 20+10; 16 const int MAXN = 1e3+10; 17 18 int uN, vN, Rank[MAXN][MAXM]; 19 int num[MAXM], linker[MAXM][MAXN]; 20 bool g[MAXN][MAXM], used[MAXM]; 21 22 bool dfs(int u) 23 { 24 for(int v = 1; v<=vN; v++) 25 if(g[u][v] && !used[v]) 26 { 27 used[v] = true; 28 if(linker[v][0]<num[v]) 29 { 30 linker[v][++linker[v][0]] = u; 31 return true; 32 } 33 for(int i = 1; i<=num[v]; i++) 34 if(dfs(linker[v][i])) 35 { 36 linker[v][i] = u; 37 return true; 38 } 39 } 40 return false; 41 } 42 43 bool hungary() 44 { 45 for(int i = 1; i<=vN; i++) 46 linker[i][0] = 0; 47 for(int u = 1; u<=uN; u++) 48 { 49 memset(used, false, sizeof(used)); 50 if(!dfs(u)) return false; 51 } 52 return true; 53 } 54 55 bool test(int mid) 56 { 57 for(int down = 1; down<=vN-mid+1; down++) 58 { 59 int up = down+mid-1; 60 memset(g, false, sizeof(g)); 61 for(int i = 1; i<=uN; i++) 62 for(int j = down; j<=up; j++) 63 g[i][Rank[i][j]] = true; 64 65 if(hungary()) return true; 66 } 67 return false; 68 } 69 70 int main() 71 { 72 while(scanf("%d%d", &uN, &vN)!=EOF) 73 { 74 for(int i = 1; i<=uN; i++) 75 for(int j = 1; j<=vN; j++) 76 scanf("%d", &Rank[i][j]); 77 78 for(int i = 1; i<=vN; i++) 79 scanf("%d", &num[i]); 80 81 int l = 1, r = vN; 82 while(l<=r) 83 { 84 int mid = (l+r)>>1; 85 if(test(mid)) 86 r = mid - 1; 87 else 88 l = mid + 1; 89 } 90 printf("%d\n", l); 91 } 92 }View Code
最大流:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <string> 6 #include <vector> 7 #include <map> 8 #include <set> 9 #include <queue> 10 #include <sstream> 11 #include <algorithm> 12 using namespace std; 13 const int INF = 2e9; 14 const int MOD = 1e9+7; 15 const int MAXM = 20+10; 16 const int MAXN = 2e3+10; 17 18 struct Edge 19 { 20 int to, next, cap, flow; 21 }edge[MAXN*MAXN]; 22 int tot, head[MAXN]; 23 24 int uN, vN, Rank[MAXN][MAXM], num[MAXM]; 25 int gap[MAXN], dep[MAXN], pre[MAXN], cur[MAXN]; 26 27 void add(int u, int v, int w) 28 { 29 edge[tot].to = v; edge[tot].cap = w; edge[tot].flow = 0; 30 edge[tot].next = head[u]; head[u] = tot++; 31 edge[tot].to = u; edge[tot].cap = 0; edge[tot].flow = 0; 32 edge[tot].next = head[v]; head[v] = tot++; 33 } 34 35 int sap(int start, int end, int nodenum) 36 { 37 memset(gap,0,sizeof(gap)); 38 memset(dep,0,sizeof(dep)); 39 memcpy(cur,head,sizeof(head)); 40 41 int u = start; 42 pre[u] = -1; 43 gap[0] = nodenum; 44 int maxflow = 0; 45 while(dep[start]<nodenum) 46 { 47 bool flag = false; 48 for(int i = cur[u]; i!=-1; i=edge[i].next) 49 { 50 int v = edge[i].to; 51 if(edge[i].cap-edge[i].flow && dep[v]+1==dep[u]) 52 { 53 flag = true; 54 cur[u] = pre[v] = i; 55 u = v; 56 break; 57 } 58 } 59 60 if(flag) 61 { 62 if(u==end) 63 { 64 int minn = INF; 65 for(int i = pre[u]; i!=-1; i=pre[edge[i^1].to]) 66 if(minn>edge[i].cap-edge[i].flow) 67 minn = edge[i].cap-edge[i].flow; 68 for(int i = pre[u]; i!=-1; i=pre[edge[i^1].to]) 69 { 70 edge[i].flow += minn; 71 edge[i^1].flow -= minn; 72 } 73 u = start; 74 maxflow += minn; 75 } 76 } 77 78 else 79 { 80 int minn = nodenum; 81 for(int i = head[u]; i!=-1; i=edge[i].next) 82 if(edge[i].cap-edge[i].flow && dep[edge[i].to]<minn) 83 { 84 minn = dep[edge[i].to]; 85 cur[u] = i; 86 } 87 gap[dep[u]]--; 88 if(gap[dep[u]]==0) break; 89 dep[u] = minn+1; 90 gap[dep[u]]++; 91 if(u!=start) u = edge[pre[u]^1].to; 92 } 93 } 94 return maxflow; 95 } 96 97 bool test(int mid) 98 { 99 for(int down = 1; down<=vN-mid+1; down++) 100 { 101 tot = 0; 102 memset(head, -1, sizeof(head)); 103 for(int i = 1; i<=uN; i++) 104 { 105 add(0, i, 1); 106 int up = down+mid-1; 107 for(int j = down; j<=up; j++) 108 add(i, uN+Rank[i][j], 1); 109 } 110 for(int i = 1; i<=vN; i++) 111 add(uN+i, uN+vN+1, num[i]); 112 113 int maxflow = sap(0, uN+vN+1, uN+vN+2); 114 if(maxflow==uN) return true; 115 } 116 return false; 117 } 118 119 int main() 120 { 121 while(scanf("%d%d", &uN, &vN)!=EOF) 122 { 123 for(int i = 1; i<=uN; i++) 124 for(int j = 1; j<=vN; j++) 125 scanf("%d", &Rank[i][j]); 126 127 for(int i = 1; i<=vN; i++) 128 scanf("%d", &num[i]); 129 130 int l = 1, r = vN; 131 while(l<=r) 132 { 133 int mid = (l+r)>>1; 134 if(test(mid)) 135 r = mid - 1; 136 else 137 l = mid + 1; 138 } 139 printf("%d\n", l); 140 } 141 }View Code
POJ3189 Steady Cow Assignment —— 二分圖多重匹配/最大流 + 二分