社区讨论
dinic 6个点TLE 求助……
P2764最小路径覆盖问题参与者 2已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @mi6mffwe
- 此快照首次捕获于
- 2025/11/20 07:16 4 个月前
- 此快照最后确认于
- 2025/11/20 07:16 4 个月前
CPP
#include <cstdio>
#include <queue>
#include <memory.h>
using namespace std;
const int MAXN = 10000;
const int INF = 1<<29;
int n, m, tot=1, front[MAXN], layer[MAXN]; //1~n:x n+1~2n:y 2n+1:s 2n+2:t
int s, t, ans=0;
bool is_start[MAXN];
struct tEdge
{
int v, next;
int c, f;
inline void addEdge(int tmpu, int tmpv, int tmpc)
{
v = tmpv; c = tmpc;
next = front[tmpu];
front[tmpu] = tot;
f = 0;
}
} e[MAXN*10];
bool bfs()
{
queue <int> q;
memset(layer, 0, sizeof(layer));
layer[s] = 1; q.push(s);
while(!q.empty())
{
int u = q.front(); q.pop();
for(int i=front[u]; i>0; i=e[i].next)
{
int v = e[i].v, maxflow = e[i].c - e[i].f;
if(layer[v] != 0) continue;
if(maxflow <= 0) continue;
layer[v] = layer[u] +1;
q.push(v);
}
}
if(layer[t] == 0) return false;
return true;
}
int dfs(int u, int curflow)
{
if(u == t || curflow == 0) return curflow;
int flow = 0;
for(int i=front[u]; i>0; i=e[i].next)
{
int v = e[i].v, maxflow = e[i].c - e[i].f;
if(layer[v] != layer[u] +1) continue;
if(maxflow <= 0) continue;
int addflow = dfs(v, min(curflow, maxflow));
flow += addflow;
curflow -= addflow;
e[i].f += addflow;
e[i^1].f -= addflow;
if(curflow == 0) break;
}
return flow;
}
int dinic()
{
int flow = 0;
while(bfs() == true)
flow += dfs(s, INF);
return flow;
}
void output_dfs(int u)
{
printf("%d ", u);
for(int i=front[u]; i>0; i=e[i].next)
{
int v = e[i].v;
if(e[i].f != 1) continue;
output_dfs(v - n);
}
}
int main()
{
scanf("%d%d", &n, &m);
s = 2*n+1; t = s*n+2;
for(int i=1; i<=n; i++) //连接原点 汇点
{
e[++tot].addEdge(s, i, 1);
e[++tot].addEdge(i, s, 0);
e[++tot].addEdge(n+i, t, 1);
e[++tot].addEdge(t, n+1, 0);
}
for(int i=1; i<=m; i++) //拆点 连边
{
int tmpx, tmpy;
scanf("%d%d", &tmpx, &tmpy);
e[++tot].addEdge(tmpx, tmpy+n, 1);
e[++tot].addEdge(tmpy+n, tmpx, 0);
}
int maxflow = dinic(); //dinic求最大流
memset(is_start, true, sizeof(is_start));
for(int i=2; i<=tot; i++) //输出方案
if(e[i].f == 1 && e[i].v >n && e[i].v <=2*n)
is_start[e[i].v - n] = false; //如果一个点不是一条路径的起点,则标记为false
for(int i=1; i<=n; i++)
if(is_start[i] == true)
{ output_dfs(i); ans ++; printf("\n"); } //从每个路径的节点深搜并输出该路径,每有一个路径ans +1;
printf("%d\n", ans); //输出答案
return 0;
}
回复
共 2 条回复,欢迎继续交流。
正在加载回复...