P3356 火星探险问题
考虑拆点,每个点对
最后输出方案时,从起点
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
#define int long long
const int N = 5e5 + 5, M = 40;
int n, p, q, ec[M][M];
int e[N], h[N], c[N], cs[N], ne[N], idx, S = 0, T;
int ll[M][M][2];
int nowp = 0;
int dx[] = { 1, 0 };
int dy[] = { 0, 1 };
int dis[N], cur[N];
bool isin[N];
inline int get_in(int x, int y)
{
return (x - 1) * q + y;
}
inline int get_out(int x, int y)
{
return get_in(x, y) + p * q;
}
inline void add(int u, int v, int w, int g)
{
g = -g;
e[idx] = v, c[idx] = w, cs[idx] = g, ne[idx] = h[u], h[u] = idx++;
e[idx] = u, c[idx] = 0, cs[idx] = -g, ne[idx] = h[v], h[v] = idx++;
}
inline bool spfa()
{
for (int i = 0; i <= T; i++) dis[i] = INT_MAX, cur[i] = -1;
queue<int> q;
q.push(S);
dis[S] = 0, cur[S] = h[S];
while (q.size())
{
int u = q.front();
q.pop();
isin[u] = 0;
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (dis[j] > dis[u] + cs[i] && c[i] > 0)
{
cur[j] = h[j];
dis[j] = dis[u] + cs[i];
if (!isin[j])
{
q.push(j);
isin[j] = 1;
}
}
}
}
return (dis[T] != INT_MAX);
}
inline int dfs(int u, int lim)
{
if (u == T) return lim;
isin[u] = 1;
int sum = 0;
for (int i = cur[u]; ~i && sum < lim; i = ne[i])
{
cur[u] = i;
int j = e[i];
if (dis[j] == dis[u] + cs[i] && c[i] > 0 && !isin[j])
{
int p = dfs(j, min(lim - sum, c[i]));
sum += p;
c[i] -= p;
c[i ^ 1] += p;
}
}
isin[u] = 0;
return sum;
}
int dinic()
{
int res = 0, p;
while (spfa())
{
while (p = dfs(S, INT_MAX)) res += p;
}
return res;
}
void dfss(int x, int y)
{
if (x == p && y == q)
{
return;
}
int g = get_out(x, y);
if (ll[x][y][0] != -1 && c[ll[x][y][0] ^ 1] > 0)
{
printf("%d %d\n", nowp, 0);
c[ll[x][y][0] ^ 1]--;
dfss(x + dx[0], y + dy[0]);
return;
}
if (ll[x][y][1] != -1 && c[ll[x][y][1] ^ 1] > 0)
{
printf("%d %d\n", nowp, 1);
c[ll[x][y][1] ^ 1]--;
dfss(x + dx[1], y + dy[1]);
return;
}
}
signed main()
{
memset(h, -1, sizeof h);
memset(ll, -1, sizeof ll);
S = 10000, T = 10001;
scanf("%lld%lld%lld", &n, &q, &p);
add(S, get_in(1, 1), n, 0);
add(get_out(p, q), T, n, 0);
for (int i = 1; i <= p; i++)
{
for (int j = 1; j <= q; j++) scanf("%lld", &ec[i][j]);
}
if (ec[1][1] == 1 || ec[p][q] == 1) return 0;
for (int i = 1; i <= p; i++)
{
for (int j = 1; j <= q; j++)
{
if (ec[i][j] == 1) continue;
add(get_in(i, j), get_out(i, j), INT_MAX, 0);
if (ec[i][j] == 2) add(get_in(i, j), get_out(i, j), 1, 1);
for (int k = 0; k < 2; k++)
{
int nx = i + dx[k], ny = j + dy[k];
if (nx >= 1 && nx <= p && ny >= 1 && ny <= q && ec[nx][ny] != 1)
{
add(get_out(i, j), get_in(nx, ny), INT_MAX, 0);
ll[i][j][k] = h[get_out(i, j)];
}
}
}
}
int hh = dinic();
for (int i = 1; i <= n; i++)
{
nowp = i;
dfss(1, 1);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现