标签:开始 add 链接 src isp point search open eof
题目链接:https://vjudge.net/problem/POJ-3189
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 6979 | Accepted: 2418 |
Description
Input
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
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 }
最大流:
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 }
POJ3189 Steady Cow Assignment —— 二分图多重匹配/最大流 + 二分
标签:开始 add 链接 src isp point search open eof
原文地址:http://www.cnblogs.com/DOLFAMINGO/p/7825303.html