1 条题解
-
0
自动搬运
来自洛谷,原作者为

fastle
**搬运于
2025-08-24 21:47:01,当前版本为作者最后更新于2017-12-24 21:19:52,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
/* 网络流的二分图匹配问题
可以直观的想到,二分图的左边是单位,右边是桌子
由于我们的特殊限制 每个单位只能在一个桌子坐一个人
所以我们就把每个单位向各个桌子连一道流量为1的边
由源点向每个单位连上 连上单位人数的边
由每个圆桌向汇点连上 圆桌人数的边
然后跑一下最大匹配 如果最大匹配数等于所有单位的人数和
那么就可以 完全安排 否则不能完全安排
这个题目的统计答案要比前两个好弄一点 枚举即可
*/
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #define INF 0x3e3e3e3e #include<queue> #define MAXN 100010 using namespace std; struct Edge{ int to; int nxt; int cup; int flow; }edge[MAXN << 1]; int deep[MAXN]; int head[MAXN]; int cnt = 1,ans = 0; int n,m,s,t; queue<int>q; int read() { int nm = 0,f = 1; char c = getchar(); for(;!isdigit(c);c = getchar())if(c == '-')f = -1; for(;isdigit(c);c = getchar())nm = nm * 10 + c - '0'; return nm * f; } void push(int vi,int vj,int wei) { cnt++;edge[cnt].to = vj;edge[cnt].cup = wei;edge[cnt].nxt = head[vi];head[vi] = cnt; cnt++;edge[cnt].to = vi;edge[cnt].nxt = head[vj];head[vj] = cnt; } bool bfs(int be,int ed) { while(!q.empty()) q.pop(); memset(deep,0,sizeof(deep)); deep[be] = 1; q.push(be); while(!q.empty()) { int op = q.front(); q.pop(); for(int i = head[op]; i; i = edge[i].nxt) { int vj = edge[i].to; if(deep[vj] || edge[i].cup <= edge[i].flow)continue; deep[vj] = deep[op] + 1; q.push(vj); if(vj == ed) return true; } } return false; } int dfs(int now,int ed,int flow) { if(flow == 0 || now == ed)return flow; int tot = 0,f; for(int i = head[now];i;i = edge[i].nxt) { int vj = edge[i].to; if(deep[vj] != deep[now] + 1)continue; int op = min(edge[i].cup - edge[i].flow,flow); if(f = dfs(vj,ed,op)) { edge[i].flow += f; edge[i ^ 1].flow -= f; tot += f; flow -= f; } if(flow == 0)break; } if(tot == 0)deep[now] = 0; return tot; } void Dinic(int be,int ed) { while(bfs(be,ed)) ans -= dfs(be,ed,INF); } int main() { n = read();m = read();s = n + m + 1;t = s + 1; for(int i = 1;i <= n;i++) { for(int j = 1;j <= m;j++) { push(i,j + n,1); } } for(int i = 1;i <= n;i++) { int op = read(); push(s,i,op); ans += op; } for(int j = 1;j <= m;j++) { int op = read(); push(j + n,t,op); } Dinic(s,t); if(ans == 0){ printf("1\n"); for(int i = 1;i <= n;i++) { for(int j = head[i];j;j = edge[j].nxt) { int vj = edge[j].to; if(vj != s && edge[j].flow) { printf("%d ",edge[j].to - n); } } printf("\n"); } } else{ printf("0\n"); } return 0; }
- 1
信息
- ID
- 2327
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者