【网络流24题】圆桌聚餐
2017-11-16 21:43
477 查看
LOJ 6004 【网络流24题】圆桌聚餐
题面
假设有来自\(n\)个不同单位的代表参加一次国际会议。每个单位的代表数分别为\(r_i\)。会议餐厅共有\(m\)张餐桌,每张餐桌可容纳\(c_i\)个代表就餐。
为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。
试设计一个算法,给出满足要求的代表就餐方案。
题解
- 源点向每个单位连一条边,边权是该单位人数;
- 每个单位向各个餐桌连一条边,边权是1;
- 每个餐桌向汇点连一条边,边权是餐桌容纳人数。
如果最大流 < 总人数,则无解。若有解,根据单位和餐桌之间哪些边跑满了来输出具体方案即可。
我犯过的错误:源点汇点的编号标错了……
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef long long ll; #define space putchar(' ') #define enter putchar('\n') template <class T> bool read(T &x){ char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; else if(c == EOF) return 0; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; return 1; } template <class T> void write(T x){ if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } const int N = 4005, M = 2000005, INF = 0x3f3f3f3f; int ncnt, n, m, s, t, ans, sum; int ecnt = 1, adj , nxt[M], go[M], cap[M], cur ; int que , qr, lev , stk , top; void ADD(int u, int v, int w){ go[++ecnt] = v; nxt[ecnt] = adj[u]; adj[u] = ecnt; cap[ecnt] = w; } void add(int u, int v, int w){ ADD(u, v, w), ADD(v, u, 0); } bool bfs(){ for(int i = 1; i <= ncnt; i++) lev[i] = -1, cur[i] = adj[i]; lev[s] = 0, que[qr = 1] = s; for(int ql = 1; ql <= qr; ql++){ int u = que[ql]; for(int e = adj[u], v; e; e = nxt[e]) if(cap[e] && lev[v = go[e]] == -1){ lev[v] = lev[u] + 1, que[++qr] = v; if(v == t) return 1; } } return 0; } int dinic(int u, int flow){ if(u == t) return flow; int delta, ret = 0; for(int &e = cur[u], v; e; e = nxt[e]) if(cap[e] && lev[v = go[e]] > lev[u]){ delta = dinic(v, min(cap[e], flow - ret)); if(delta){ cap[e] -= delta; cap[e ^ 1] += delta; ret += delta; if(ret == flow) return flow; } } lev[u] = -1; return ret; } int main(){ read(m), read(n); ncnt = n + m + 2, s = ncnt - 1, t = ncnt; for(int i = 1, val; i <= m; i++) read(val), add(s, i, val), sum += val; for(int i = 1, val; i <= n; i++) read(val), add(i + m, t, val); for(int i = 1; i <= m; i++) for(int j = 1; j <= n; j++) add(i, j + m, 1); while(bfs()) ans += dinic(s, INF); if(ans < sum){ puts("0"); return 0; } puts("1"); for(int u = 1; u <= m; u++){ for(int e = adj[u]; e; e = nxt[e]) if(!(e & 1) && !cap[e]) write(go[e] - m), space; enter; } return 0; }
相关文章推荐
- COGS 729 [网络流24题] 圆桌聚餐
- [网络流24题] 圆桌聚餐 最大流/路径输出
- COGS729. [网络流24题] 圆桌聚餐
- [网络流24题] 05 圆桌聚餐(最大流判满流)
- [Loj]#6004. 「网络流 24 题」圆桌聚餐
- loj #6004. 「网络流 24 题」圆桌聚餐(最大流)
- 【网络流24题】圆桌聚餐(二分图)
- COGS 729. [网络流24题] 圆桌聚餐
- loj6004「网络流 24 题」圆桌聚餐
- Libre 6004 「网络流 24 题」圆桌聚餐(网络流,最大流)
- 网络流24题 圆桌聚餐
- LOJ6004 「网络流 24 题 - 5」圆桌聚餐 最大流
- 【网络流24题】圆桌聚餐(最大流)
- 【PowerOJ1740&网络流24题 圆桌聚餐】(最大流)
- cogs 729. [网络流24题] 圆桌聚餐
- [网络流24题-4]cogs729 圆桌聚餐
- [网络流24题]圆桌聚餐
- [网络流24题] 圆桌聚餐
- 网络流24题 05圆桌聚餐
- 「网络流 24 题」圆桌聚餐