社区讨论

神秘效率问题求问

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;
}```
第二份代码:多路同时增广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;
}```
第二份代码还加了炸点优化,为什么这么慢??
老师的代码(逻辑与代码二完全一致,约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 条回复,欢迎继续交流。

正在加载回复...