// 模板。(匈牙利的稍微改写) 和 例题(最下面) 一般多重匹配需要配合二分查找答案
// 例题 :hdu 3605
// 题意:有n(n <= 100000)个人和m(m <= 10)个星球, 每个人有自己想去的星球(不止一个), 但每个星球能承受的人数不同。问: 能不能把所有人安排到他自己想去的星球上;
// 输入(机翻):
//输出 YES or NO
1 #include<iostream> 2 #define read(n) n = read_n() 3 #define rep(i, n) for(int i=0;i!=n;++i) 4 #define rep1(i, n) for(int i=1;i<=n;++i) 5 using namespace std; 6 7 inline int read_n() { 8 char c=getchar();int x=0,f=1; 9 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 10 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 11 return x*f; 12 } 13 // ----------------------------------------------------- 14 const int MAXN = 100000+5; 15 const int MAXM = 10+5; 16 const int MAXE = MAXN*MAXM; 17 18 int num; 19 int head[MAXN]; 20 struct node { 21 int v, next; 22 } edge[MAXE]; 23 24 inline void add(int x, int y) { 25 edge[num].v = y; 26 edge[num].next = head[x]; 27 head[x] = num++; 28 } 29 30 int n, m; 31 int maxn[MAXM]; 32 33 int cnt[MAXM]; 34 int love[MAXM][MAXN];// love[i][j]表示i星球的第j位置匹配到了某人 35 bool vis[MAXM]; 36 // -----------------核心---------------------- 37 bool dfs(int u) { 38 for(int i = head[u]; i != -1; i = edge[i].next) { 39 int v = edge[i].v; 40 if(!vis[v]) { 41 vis[v] = true; 42 if(cnt[v] < maxn[v]) {// 如果v还有"位置"匹配 43 love[v][++cnt[v]] = u; 44 return true; 45 } 46 for(int j = 1; j <= cnt[v]; ++j) {// 若没有位置了, 从已经匹配的上面找是否有人能腾出位置 47 if(dfs(love[v][j])) { 48 love[v][j] = u; 49 return true; 50 } 51 } 52 } 53 } 54 return false; 55 } 56 // --------------------------------------------- 57 bool solve() { 58 rep1(i, m) cnt[i] = 0; 59 rep1(i, n) { 60 rep1(j, m) vis[j] = false; 61 if(!dfs(i)) return false; 62 } 63 return true; 64 } 65 66 int main() { 67 while(cin >> n >> m) { 68 num = 0; 69 rep1(i, n) head[i] = -1; 70 int x; 71 rep1(i, n) rep1(j, m) { 72 read(x); 73 if(x == 1) add(i, j); 74 } 75 rep1(i, m) read(maxn[i]); 76 if(solve()) cout << "YES "; 77 else cout << "NO "; 78 } 79 return 0; 80 }
// poj 2289 二分查找答案
1 #include<iostream> 2 #include<sstream> 3 #include<cstdlib> 4 using namespace std; 5 6 const int MAXN = 1000+5; 7 const int MAXM = 500+5; 8 const int MAXE = MAXN*MAXM; 9 10 int num; 11 int head[MAXN]; 12 struct node { 13 int v, next; 14 } edge[MAXE]; 15 16 inline void add(int x, int y) { 17 edge[num].v = y; 18 edge[num].next = head[x]; 19 head[x] = num++; 20 } 21 22 int n, m, maxn; 23 string str; 24 25 int cnt[MAXN]; 26 int love[MAXN][MAXM]; 27 bool vis[MAXN]; 28 29 bool dfs(int u) { 30 for(int i = head[u]; i != -1; i = edge[i].next) { 31 int v = edge[i].v; 32 if(!vis[v]) { 33 vis[v] = true; 34 if(cnt[v] < maxn) { 35 love[v][++cnt[v]] = u; 36 return true; 37 } 38 for(int j = 1; j <= cnt[v]; ++j) { 39 if(dfs(love[v][j])) { 40 love[v][j] = u; 41 return true; 42 } 43 } 44 } 45 } 46 return false; 47 } 48 49 bool hungry(int p) { 50 maxn = p; 51 for(int i = 0; i != m; ++i) cnt[i] = 0; 52 for(int i = 1; i <= n; ++i) { 53 for(int j = 0; j != m; ++j) vis[j] = false; 54 if(!dfs(i)) return false; 55 } 56 return true; 57 } 58 59 int main() { 60 ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); 61 while(cin >> n >> m && n) { 62 num = 0; 63 getchar(); 64 for(int i = 1; i <= n; ++i) head[i] = -1; 65 for(int i = 1; i <= n; ++i) { 66 getline(cin, str); 67 stringstream s(str); 68 string ss; 69 while(s >> ss) { 70 if(isalpha(ss[0])) continue; 71 int p = atoi(ss.c_str()); 72 add(i, p); 73 } 74 } 75 int l = 1, r = n, mid, ans; 76 while(l <= r) { 77 mid = (l+r)/2; 78 if(hungry(mid)) ans = mid, r = mid - 1; 79 else l = mid + 1; 80 } 81 cout << ans << " "; 82 } 83 return 0; 84 }
// poj 2112 二分查找答案
1 #include<iostream> 2 #include<algorithm> 3 #include<vector> 4 #define rep(i, n) for(int i=0;i!=n;++i) 5 #define rep1(i, n) for(int i=1;i<=n;++i) 6 #define Rep1(i, sta, n) for(int i=sta;i<=n;++i) 7 using namespace std; 8 // ----------------------------------------------------- 9 const int MAXN = 230+5; 10 const int MAXE = MAXN*MAXN; 11 12 int num; 13 int head[MAXN]; 14 struct node { 15 int v, next; 16 } edge[MAXE]; 17 18 inline void add(int x, int y) { 19 edge[num].v = y; 20 edge[num].next = head[x]; 21 head[x] = num++; 22 } 23 24 int n, m, nm, maxn, dis; 25 int G[MAXN][MAXN]; 26 27 int cnt[MAXN]; 28 int love[MAXN][MAXN]; 29 bool vis[MAXN]; 30 31 bool dfs(int u) { 32 for(int i = head[u]; i != -1; i = edge[i].next) { 33 int v = edge[i].v; 34 if(G[u][v] > dis) continue; 35 if(!vis[v]) { 36 vis[v] = true; 37 if(cnt[v] < maxn) { 38 love[v][++cnt[v]] = u; 39 return true; 40 } 41 for(int j = 1; j <= cnt[v]; ++j) { 42 if(dfs(love[v][j])) { 43 love[v][j] = u; 44 return true; 45 } 46 } 47 } 48 } 49 return false; 50 } 51 52 bool solve(int d) { 53 dis = d; 54 rep1(i, m) cnt[i] = 0; 55 Rep1(i, m+1, nm) { 56 rep1(j, m) vis[j] = false; 57 if(!dfs(i)) return false; 58 } 59 return true; 60 } 61 62 int main() { 63 ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); 64 cin >> m >> n >> maxn; 65 nm = n+m; 66 num = 0; 67 rep1(i, nm) head[i] = -1; 68 rep1(i, nm) rep1(j, nm) cin >> G[i][j]; 69 rep1(k, nm) { 70 rep1(i, nm) { 71 if(G[i][k]) rep1(j, nm) if(G[k][j]) if(!G[i][j] || G[i][k]+G[k][j] < G[i][j]) { 72 G[i][j] = G[i][k] + G[k][j]; 73 } 74 } 75 } 76 vector<int> v; 77 Rep1(i, m+1, nm) { 78 Rep1(j, 1, m) if(G[i][j]) add(i, j), v.push_back(G[i][j]); 79 } 80 sort(v.begin(), v.end()); 81 int l = 0, r = unique(v.begin(), v.end()) - v.begin()-1; 82 int mi, ans; 83 while(l <= r) { 84 mi = (l+r)>>1; 85 if(solve(v[mi])) ans = v[mi], r = mi-1; 86 else l = mi+1; 87 } 88 cout << ans << " "; 89 return 0; 90 }
// poj 3189 二分+枚举约束条件找答案
1 /* 2 * @Promlem: 3 * @Time Limit: ms 4 * @Memory Limit: k 5 * @Author: pupil-XJ 6 * @Date: 2019-11-04 23:50:39 7 * @LastEditTime: 2019-11-05 00:27:17 8 */ 9 #include<cstdio> 10 using namespace std; 11 const int MAXN = 1000+5; 12 const int MAXM = 20+5; 13 const int MAXE = MAXN*MAXM; 14 15 int num; 16 int head[MAXN]; 17 struct node { 18 int v, w, next; 19 } edge[MAXE]; 20 21 inline void add(int x, int y, int w) { 22 edge[num].v = y; 23 edge[num].w = w; 24 edge[num].next = head[x]; 25 head[x] = num++; 26 } 27 28 int n, m; 29 int G[MAXN][MAXM]; 30 int maxn[MAXM]; 31 32 int cnt[MAXM]; 33 int love[MAXM][MAXN]; 34 bool vis[MAXM]; 35 36 bool dfs(int u, int l, int r) { 37 for(int i = head[u]; i != -1; i = edge[i].next) { 38 int v = edge[i].v; 39 if(edge[i].w < l || edge[i].w > r) continue; 40 if(!vis[v]) { 41 vis[v] = true; 42 if(cnt[v] < maxn[v]) { 43 love[v][++cnt[v]] = u; 44 return true; 45 } 46 for(int j = 1; j <= cnt[v]; ++j) { 47 if(dfs(love[v][j], l, r)) { 48 love[v][j] = u; 49 return true; 50 } 51 } 52 } 53 } 54 return false; 55 } 56 57 bool solve(int l, int r) { 58 for(int i = 1; i <= m; ++i) cnt[i] = 0; 59 for(int i = 1; i <= n; ++i) { 60 for(int j = 1; j <= m; ++j) vis[j] = false; 61 if(!dfs(i, l, r)) return false; 62 } 63 return true; 64 } 65 66 int main() { 67 scanf("%d%d", &n, &m); 68 num = 0; 69 for(int i = 1; i <= n; ++i) head[i] = -1; 70 for(int i = 1; i <= n; ++i) { 71 for(int j = 1; j <= m; ++j) { 72 scanf("%d", &G[i][j]); 73 add(i, G[i][j], j); 74 } 75 } 76 for(int i = 1; i <= m; ++i) scanf("%d", &maxn[i]); 77 int l = 1, r = m; 78 int mid, ans; 79 while(l <= r) { 80 bool flag = false; 81 mid = (l+r)>>1; 82 for(int i = 1; i+mid-1<=m; ++i) { 83 if(solve(i, i+mid-1)) ans = mid, flag = true; 84 if(flag) break; 85 } 86 if(flag) r = mid-1; 87 else l = mid+1; 88 } 89 printf("%d ", ans); 90 return 0; 91 }