HDU-3605 Escape(状态压缩+最大流求多重匹配、改版匈牙利算法)
来源:互联网 发布:mac打开文件夹命令 编辑:程序博客网 时间:2024/05/16 07:57
题意:
n个人,m个星球,每个人只愿意往特定的星球搬迁,而每个星球有一个最大允许居住数量。问能否将每个人都安排好居住的星球。(n <= 1e5, m <= 10)
思路:
其实就是裸的二分图的多重匹配,但是由于n较大,直接做肯定会超时。但发现m较小,所以我们先通过m将所有人的状态压缩成2^10个,然后用网络流就可以做了。
还有一种改版的匈牙利做法。即我们记录一下被匹配的点(即B部的点)已经匹配了多少个点,它能够匹配的最大数量就是它的上限。如果此时不足上限,那么就直接匹配成功并记录下来,如果达到上限,那么我们就像匈牙利最初的算法那样去尝试已经匹配了这个点的所有的点能否去匹配新的点。如此递归,由于m很小,所以最深顶多达到m个深度,即复杂度为O(n*m);
代码1:
#include <algorithm> #include <iostream> #include <string.h> #include <cstdio> #include <queue> using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 1100; const int maxm = 25000; struct node{int w; int v, next;} edge[maxm]; int pre[maxn], rec[maxn], head[maxn], gap[maxn], now[maxn]; int dis[maxn]; int t, n, m, no, up; int S, T; queue<int> q; inline void add(int u, int v, int w) { edge[no].v = v; edge[no].w = w; edge[no].next = head[u]; head[u] = no++; edge[no].v = u; edge[no].w = 0; edge[no].next = head[v]; head[v] = no++; } inline void pre_init() { no = 0; memset(head, -1, sizeof head); } void init(int S, int T) { memset(gap, 0, sizeof gap); memset(dis, 0x3f, sizeof dis); for(int i = 0; i <= up; ++i) now[i] = head[i]; while(!q.empty()) q.pop(); dis[T] = 0; q.push(T); while(!q.empty()) { int tp = q.front(); q.pop(); ++gap[dis[tp]]; int k = head[tp]; while(k != -1) { if(dis[edge[k].v] == inf && edge[k^1].w) { dis[edge[k].v] = dis[tp]+1; q.push(edge[k].v); } k = edge[k].next; } } } int SAP(int S, int T) { int ans = 0, flow = inf; int top = S; pre[S] = S; init(S, T); while(dis[S] < up) { if(top == T) { ans += flow; while(top != S) { edge[rec[top]].w -= flow; edge[rec[top]^1].w += flow; top = pre[top]; } flow = inf; } int k = now[top]; while(k != -1) { int v = edge[k].v; if(edge[k].w && dis[top] == dis[v]+1) { flow = min(flow, edge[k].w); pre[v] = top; rec[v] = k; now[top] = k; top = v; break; } k = edge[k].next; } if(k == -1) { int mind = up; if(--gap[dis[top]] == 0) break; int k = now[top] = head[top]; while(k != -1) { if(edge[k].w && mind>dis[edge[k].v]) mind = dis[edge[k].v]; k = edge[k].next; } ++gap[dis[top] = mind+1]; top = pre[top]; } } return ans; }int dig[1<<10];void mapping() { int x, a, b; memset(dig, 0, sizeof dig);for(int i = 1; i <= n; ++i){int t = 0;for(int j = 0; j < m; ++j){scanf("%d", &x);if(x) t += (1<<j);}++dig[t];}for(int i = 0; i < (1<<10); ++i){if(!dig[i]) continue;add(S, i, dig[i]);int t = i, k = 0;while(t){++k;if(t&1) add(i, (1<<10)+k, dig[i]);t >>= 1;}} for(int i = 1; i <= m; ++i) { scanf("%d", &x); add((1<<10)+i, T, x); } } int main() { while(scanf("%d %d", &n, &m) != EOF) { up = (1<<10)+12, S = 1035, T = 1036; pre_init(); mapping(); if(SAP(S, T) == n) puts("YES"); else puts("NO"); } return 0; }
代码2:
#include <bits/stdc++.h>using namespace std;bool G[100005][15];int match[15][100005];int vis[15];int hav[15], maxx[15], cun[15][100005];int n, m;bool dfs(int u){for(int i = 1; i <= m; ++i){if(!G[u][i] || vis[i]) continue;vis[i] = 1;if(hav[i] < maxx[i]){cun[i][++hav[i]] = u;return true;}else{for(int j = 1; j <= hav[i]; ++j)if(dfs(cun[i][j])){cun[i][hav[i]] = u;return true;}}}return false;} bool work(){memset(hav, 0, sizeof hav); for(int i = 1; i <= n; ++i){memset(vis, 0, sizeof vis);if(!dfs(i)) return false;}return true;}int main(){while(scanf("%d %d", &n, &m) != EOF){for(int i = 1; i <= n; ++i)for(int j = 1; j <= m; ++j)scanf("%d", &G[i][j]);for(int i = 1; i <= m; ++i)scanf("%d", &maxx[i]);if(work()) puts("YES");else puts("NO");}return 0;}
继续加油~
阅读全文
1 0
- HDU-3605 Escape(状态压缩+最大流求多重匹配、改版匈牙利算法)
- hdu 3605 Escape(最大流+状态压缩 or 二分图多重匹配)
- HDU 3605 Escape(最大流+状态压缩)
- hdu 3605 Escape 状态压缩+最大流
- HDU 3605 Escape(最大流+状态压缩)
- HDU 3605 Escape(最大流+状态压缩)
- hdu 3605 Escape (最大流+状态压缩)
- hdu 3605 Escape 多重匹配模板 (Hungary ) | 最大流
- hdu 3605 Escape 二分图的多重匹配(匈牙利算法)
- hdu 3605 Escape【图论-网络流-最大流-状态压缩】
- HDU 3605 —— Escape 状态压缩+最大流
- hdu 3605 Escape【状态压缩+最大流Dinic+建图】
- HDU - 3605 Escape(最大流+状态压缩)
- 匈牙利算法求最大匹配
- 匈牙利算法求最大匹配
- HDU--3605 Escape (多重匹配)
- hdu 4160 Dolls 匈牙利算法求最大匹配
- HDU 4160 Dolls 匈牙利算法求最大匹配数
- STL讲解 容器(map,set,vector,stack,queue)
- CentOS下使用crontab命令来定时执行任务
- 最小生成树 Freckles
- MongoDB:更改数据库位置(Windows)
- Java并发编程 01 并发注意事项
- HDU-3605 Escape(状态压缩+最大流求多重匹配、改版匈牙利算法)
- 简单dos命令
- 《程序设计入门—Java语言.翁恺》第五周编程作业(2)-井字棋
- 图灵奖得主姚期智最新论文出炉!中秋人家看月亮,AI人看论文
- 网站制作常见中英文
- switch语句的简单使用
- 纪念自己的博客开张哦
- SSH框架的整合---xml方式
- HDU 6103 Kirinriki(思维尺取)