[lnsyoj2593/luoguP3254] 圆桌问题
题解
有来自 个不同单位的代表参加一次国际会议。第 个单位派出了 个代表。
会议的餐厅共有 张餐桌,第 张餐桌可容纳 个代表就餐。
为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。请给出一个满足要求的代表就餐方案。
sol
可将单位视为左侧点,餐桌视为右侧点。
首先建立超级源点 与超级汇点 , 与第 个左侧点连接一条容量为 的边,第 个右侧点与 连接一条容量为 的边,最后在每一对左侧点和右侧点间连一条容量为 的边,跑最大流即可。当且仅当最大流 时,有合法方案。输出方案时枚举每一条左右侧点之间的边即可。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int N = 505, M = 82005, INF = 0x3f3f3f3f;
int h[N], e[M], f[M], ne[M], idx;
int d[N], cur[N];
int r[N], c[N];
int n, rn, cn;
int S, T;
void add(int a, int b, int c){
e[idx] = b, f[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
e[idx] = a, f[idx] = 0, ne[idx] = h[b], h[b] = idx ++ ;
}
void build(){
memset(h, -1, sizeof h);
n = rn + cn + 2, S = n - 1, T = n;
for (int i = 1; i <= rn; i ++ )
for (int j = 1; j <= cn; j ++ )
add(i, rn + j, 1);
for (int i = 1; i <= rn; i ++ ) add(S, i, r[i]);
for (int i = 1; i <= cn; i ++ ) add(rn + i, T, c[i]);
}
bool bfs(){
memset(d, -1, sizeof d);
queue<int> q;
d[S] = 0, cur[S] = h[S], q.push(S);
while (!q.empty()) {
int t = q.front(); q.pop();
for (int i = h[t]; ~i; i = ne[i]){
int j = e[i];
if (d[j] == -1 && f[i]) {
d[j] = d[t] + 1;
cur[j] = h[j];
if (j == T) return true;
q.push(j);
}
}
}
return false;
}
int find(int u, int limit) {
if (u == T) return limit;
int flow = 0;
for (int i = cur[u]; ~i && flow < limit; i = ne[i]){
int j = e[i];
cur[u] = i;
if (d[j] == d[u] + 1 && f[i]) {
int t = find(j, min(limit - flow, f[i]));
if (!t) d[j] = -1;
f[i] -= t, f[i ^ 1] += t, flow += t;
}
}
return flow;
}
int dinic(){
int res = 0, flow;
while (bfs()) while (flow = find(S, INF)) res += flow;
return res;
}
void print(){
for (int i = 1; i <= rn; i ++ ) {
for (int j = 1; j <= cn; j ++ ) {
// printf("@%d %d\n", e[2 * ((i - 1) * cn + j - 1)], e[2 * ((i - 1) * cn + j - 1) + 1]);
if (f[2 * ((i - 1) * cn + j) - 1]) printf("%d ", j);
}
puts("");
}
}
int main(){
scanf("%d%d", &rn, &cn);
int rsum = 0;
for (int i = 1; i <= rn; i ++ ) scanf("%d", &r[i]), rsum += r[i];
for (int i = 1; i <= cn; i ++ ) scanf("%d", &c[i]);
build();
int res = dinic();
if (res < rsum) return puts("0"), 0;
puts("1");
print();
}
分类:
题解 / 2025训练
标签:
图论
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现