社区讨论
神秘效率问题求问
P3376【模板】网络最大流参与者 2已保存回复 3
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @mlht7675
- 此快照首次捕获于
- 2026/02/11 17:10 上周
- 此快照最后确认于
- 2026/02/11 18:15 上周
第一份代码: dfs 中单路增广
CPP#include<bits/stdc++.h>
using namespace std;
const int N=205,M=5e4+5;
#define int long long
int h[N], tot=1;
struct edge
{
int v,w;
int nxt;
} e[M<<1];
void add(int u,int v,int w)
{
e[++tot].v=v;
e[tot].w=w;
e[tot].nxt=h[u];
h[u]=tot;
e[++tot].v=u;
e[tot].w=0;
e[tot].nxt=h[v];
h[v]=tot;
}
int lev[N];//分层
int cur[N];//当前弧
int n,m,s,t;
int dfs(int u,int flow)
{
if(u==t)return flow;
for(int &i=cur[u]; i; i=e[i].nxt)
{
int v=e[i].v,w=e[i].w;
if(lev[v]==lev[u]+1&&w>0)
{
int f=dfs(v,min(flow,w));
if(f>0)
{
e[i].w-=f;
e[i^1].w+=f;
return f;
}
}
}
return 0;
}
bool bfs()
{
memset(lev,-1,sizeof lev);
queue<int>q;
q.push(s);
lev[s]=0;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=h[u]; i; i=e[i].nxt)
{
int v=e[i].v,w=e[i].w;
if (w>0 &&lev[v]==-1)
{
lev[v]=lev[u]+1;
q.push(v);
}
}
}
return lev[t]!=-1;
}
int dinic()
{
int ans=0;
while(bfs())
{
for(int i=1; i<=n;i++)cur[i]=h[i];
int f;
while(f=dfs(s,10000000000))
{
ans+=f;
}
memset(cur,0,sizeof cur);
}
return ans;
}
signed main()
{
std::ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>s>>t;
for(int i=1; i<=m; i++)
{
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
}
cout<<dinic();
return 0;
}```
评测记录 70ms
第二份代码:多路同时增广
CPP#include<bits/stdc++.h>
using namespace std;
const int N=205,M=5e4+5;
#define int long long
int h[N], tot=1;
struct edge
{
int v,w;
int nxt;
} e[M<<1];
void add(int u,int v,int w)
{
e[++tot].v=v;
e[tot].w=w;
e[tot].nxt=h[u];
h[u]=tot;
e[++tot].v=u;
e[tot].w=0;
e[tot].nxt=h[v];
h[v]=tot;
}
int lev[N];//分层
int cur[N];//当前弧
int n,m,s,t;
int dfs(int u,int flow)
{
if(u==t)return flow;
int d = flow;
for(int &i=cur[u]; i && d > 0; i=e[i].nxt)
{
int v=e[i].v,w=e[i].w;
if(lev[v]==lev[u]+1&&w>0)
{
int f=dfs(v,min(d,w));
if(!f)lev[v] = 0;
e[i].w-=f;
e[i^1].w+=f;
d -= f;
}
}
return flow - d;
}
bool bfs(){
memset(lev, -1, sizeof lev);
queue<int> q;
q.push(s);
lev[s] = 0;
while(!q.empty()){
int u = q.front(); q.pop();
for(int i = h[u]; i; i = e[i].nxt){
int v = e[i].v, w = e[i].w;
if(w > 0 && lev[v] == -1){
lev[v] = lev[u] + 1;
if(v == t) return true;
q.push(v);
}
}
}
return lev[t] != -1;
}
int dinic(){
int ans = 0;
while(bfs()){
memcpy(cur, h, sizeof(int) * (n + 1));
int f;
while(f = dfs(s, LLONG_MAX))
ans += f;
}
return ans;
}
signed main()
{
std::ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>s>>t;
for(int i=1; i<=m; i++)
{
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
}
cout<<dinic();
return 0;
}```
评测记录 892ms
第二份代码还加了炸点优化,为什么这么慢??
老师的代码(逻辑与代码二完全一致,约70ms)
CPP#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int NN = 208, MM = 5e3 + 8, INF = 0x3f3f3f3f;
int n,m,s,t;
int dis[NN];//bfs 之后每个点的层数
struct Edge{
int to,next,val;
}edge[MM << 1];
int head[NN], cnt = 1, pre[NN];
void add_edge(int u,int v,int w){
edge[++cnt] = {v,head[u],w};
pre[u] = head[u] = cnt;
}
bool bfs(){//分层
memset(dis,0,sizeof(dis));
queue<int> q;
q.push(s);
dis[s] = 1; head[s] = pre[s];
while(!q.empty()){
int u = q.front(); q.pop();
for(int i = head[u]; i; i = edge[i].next){
int v = edge[i].to, w = edge[i].val;
if(w && !dis[v]){
q.push(v);
head[v] = pre[v];
dis[v] = dis[u] + 1;
if(v == t) return true;
}
}
}
return false;
}
ll dinic(int u,int flow){//从 u 流入 flow 流量,能够流多少到 T
if(u == t) return flow;
int res = flow;//剩下还能流多少
if(res == 0) return 0;
for(int &i = head[u]; i; i = edge[i].next){
int v = edge[i].to, w = edge[i].val;
if(w && dis[u] + 1 == dis[v]){
int get = dinic(v,min(res,w));//get: v 的流量
if(!get) dis[v] = 0; //剪枝
edge[i].val -= get;
edge[i^1].val += get;
res -= get;
}
if(res == 0) break;
}
return flow - res;
}
int main(){
ios::sync_with_stdio(false),cin.tie(0);
cin >> n >> m >> s >> t;
for(int i = 1,u,v,w; i <= m; ++i){
cin >> u >> v >> w;
add_edge(u,v,w);
add_edge(v,u,0);
}
ll ans = 0, flow = 0;
while(bfs()){//每一轮开始的时候 bfs,顺便判断 S T 是否联通
while(flow = dinic(s,INF))
ans += flow;
}
cout << ans;
} ```
优化没问题,那问题到底在哪?求大佬解答
回复
共 3 条回复,欢迎继续交流。
正在加载回复...