网络流的2种算法
查看原帖
网络流的2种算法
499682
operator_楼主2023/4/23 18:50

RT,以下2个代码据说复杂度相近,为什么只有第1个能过?第2个会T

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read() {
	int s=0,m=0;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-')m=1;ch=getchar();}
	while( isdigit(ch)) s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return m?-s:s;
}
int m,n,x,a,b,sum;
int h[2405],cnt=1;
struct QWQ{int v,w,nxt;} e[5000005];
void add(int u,int v,int w) {e[++cnt]={v,w,h[u]},h[u]=cnt;}
int cur[2405],d[2405],pre[2405],fa[2405],gap[2405];
int ISAP(int s,int t) {
	memcpy(cur,h,sizeof(h));
	gap[0]=n;
	int u=s,maxflow=0,flag=0;
	while(d[s]<n) {
		if(u==t) {
			int flow=INT_MAX;
			for(;u!=s;u=fa[u])
				flow=min(flow,e[pre[u]].w);
			for(u=t;u!=s;u=fa[u])
				e[pre[u]].w-=flow,e[pre[u]^1].w+=flow;
			maxflow+=flow;
		}
		flag=0;
		for(int i=cur[u];i;i=e[i].nxt) {
			int v=e[i].v,w=e[i].w;
			if(!w||d[u]!=d[v]+1) continue;
			flag=1,cur[u]=i;
			pre[v]=i,fa[v]=u,u=v;
			break;
		}
		if(flag) continue;
		int minn=n-1;
		for(int i=h[u];i;i=e[i].nxt) 
			if(e[i].w)
				minn=min(minn,d[e[i].v]);
		cur[u]=h[u];
		if(!(--gap[d[u]])) break;
		gap[(d[u]=minn+1)]++;
		if(u!=s) u=fa[u];
	}
	return maxflow;
}
signed main() {
	cin>>n>>m;
	for(int i=1;i<=n;i++) {
		a=read(),x=read(),sum+=a;
		add(n+m+1,i,a);add(i,n+m+1,0);
		for(int j=1;j<=x;j++) {
			a=read(),b=read();
			add(i,a+n,b);add(a+n,i,0);
		}
	}
	for(int i=1;i<=m;i++) {
		a=read();
		add(i+n,n+m+2,a);add(n+m+2,i+n,0);
	}
	n=n+m+3;
	int flow=ISAP(n-2,n-1);
	cout<<sum-flow;
	return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read() {
	int s=0,m=0;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-')m=1;ch=getchar();}
	while( isdigit(ch)) s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return m?-s:s;
}
int m,n,x,a,b,sum;
int h[2405],cnt=1;
struct QWQ{int v,w,nxt;} e[5000005];
void add(int u,int v,int w) {e[++cnt]={v,w,h[u]},h[u]=cnt;}
int d[2405],cur[2405];
queue<int> q;
bool bfs(int s,int t) {
	memset(d,0x3f,sizeof(d));
	while(q.size()) q.pop();
	q.push(s);d[s]=0;
	while(q.size()) {
		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||d[v]<(int)1e9) continue;
			q.push(v);
			d[v]=d[u]+1;
		}
	}
	if(d[t]<(int)1e9) return 1;
	return 0;
}
int dfs(int u,int t,int sum) {
	if(u==t) return sum;
	for(int i=cur[u];i;i=e[i].nxt) {
		int v=e[i].v,w=e[i].w;
		if(!w||d[v]!=d[u]+1) continue;
		int k=dfs(v,t,min(sum,w));
		if(!k) continue;
		e[i].w-=k,e[i^1].w+=k;
		return k;
	}
	return 0;
}
int Dinic(int s,int t) {
	int maxflow=0,www;
	while(bfs(s,t)) {
		memcpy(cur,h,sizeof(h));
		do {
			www=dfs(s,t,INT_MAX);
			maxflow+=www;
		} while(www);
	}
	return maxflow;
}
signed main() {
	cin>>n>>m;
	for(int i=1;i<=n;i++) {
		a=read(),x=read(),sum+=a;
		add(n+m+1,i,a);add(i,n+m+1,0);
		for(int j=1;j<=x;j++) {
			a=read(),b=read();
			add(i,a+n,b);add(a+n,i,0);
		}
	}
	for(int i=1;i<=m;i++) {
		a=read();
		add(i+n,n+m+2,a);add(n+m+2,i+n,0);
	}
	n=n+m+3;
	int flow=Dinic(n-2,n-1);
	cout<<sum-flow;
	return 0;
}

也不止这一题,很多题都只能用第1种,求解答

2023/4/23 18:50
加载中...