网络流做题记录

最大流

经典入门题目,对于每个左侧点建立与右侧点边权为1的边

建立超级源点连左侧,超级汇点连右侧,直接跑最大流

Code:

#include<bits/stdc++.h>
#define int long long
#define INF 0x3f3f3f3f
using namespace std;
const int M=2e5+110;
inline int read(){
	int sum=0,k=1;char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')k=-1;c=getchar();
	}while(c>='0'&&c<='9'){sum=sum*10+c-48;c=getchar();
	}return sum*k;
}
int Head[M],Tot=1;
struct Line_Node{
	int Next,To,Val;
}Ed[M];
inline void Adde(int u,int v,int w){
	Ed[++Tot]={Head[u],v,w};
	Head[u]=Tot;
}
int n,m,s,t,cur[M];
int Deep[M];bool vis[M];
inline bool bfs(){
	for(int i=0;i<=n+1;i++)
		Deep[i]=INF,vis[i]=false,cur[i]=Head[i];
	Deep[s]=true,vis[s]=true;
	queue<int>q;q.push(s);
	while(!q.empty()){
		int u=q.front();
		q.pop();vis[u]=false;
		for(int i=Head[u];i;i=Ed[i].Next){
			int v=Ed[i].To,w=Ed[i].Val;
			if(Deep[u]+1<Deep[v]&&w!=false){
				Deep[v]=Deep[u]+1;
				if(vis[v]==false){
					vis[v]=true;q.push(v);
				}
			}
		}
	}if(Deep[t]==INF) return false;
	 else return true;
}
inline int dfs(int u,int mi){
	int mm=0;
	if(u==t) return mi;
	for(int i=cur[u];i;i=Ed[i].Next){
		cur[u]=i;
		int v=Ed[i].To,w=Ed[i].Val;
		if(Deep[u]+1==Deep[v]&&w!=false){
			mm=dfs(v,min(w,mi));
			if(mm!=false){
				Ed[i].Val-=mm;
				Ed[i^1].Val+=mm;
				return mm;
			}
		}
	}return false;
}
inline int Dinic(){
	int ans=0,res=0;
	while(bfs())
		while(res=dfs(s,INF))
			ans+=res;
	return ans;
}
signed main(){
	m=read(),n=read();
	s=0,t=n+1;//超级源点与超级汇点 
	while(1){
		int u=read(),v=read();
		if(u==v&&u==-1) break;
		Adde(u,v,1);Adde(v,u,0);
	}//正常建边
	//各个点与源点,汇点连边 
	for(int i=1;i<=m;i++) Adde(s,i,1),Adde(i,s,0);
	for(int i=m+1;i<=n;i++) Adde(i,t,1),Adde(t,i,0);
	cout<<Dinic()<<endl;
	for(int i=2;i<=Tot;i+=2){
		if(Ed[i].To==s||Ed[i^1].To==s)
			continue;
		if(Ed[i].To==t||Ed[i^1].To==t)
			continue;
		if(Ed[i^1].Val!=false)//当正反边存在边权时,为流经点 
			cout<<Ed[i^1].To<<" "<<Ed[i].To<<endl;
	}
	return 0;
} 

二分图思想,把每个单位与每个桌子连流量为1的边,源点与单位连人数边,桌子与汇点连容量边

暴力枚举方案数

Code:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define int long long
using namespace std;
const int M=2e5+110;
inline int read(){
	int sum=0,k=1;char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')k=-1;c=getchar();
	}while(c>='0'&&c<='9'){sum=sum*10+c-48;c=getchar();
	}return sum*k;
}
struct Line_Node{
	int Next,To,Val;
}Ed[M];
int Head[M],Tot=1;
inline void Adde(int u,int v,int w){
	Ed[++Tot]={Head[u],v,w};
	Head[u]=Tot;
}
int n,m,s,t,sum,cur[M];
int Deep[M];bool vis[M];
inline bool bfs(){
	for(int i=0;i<=n+m+1;i++) 
		Deep[i]=INF,vis[i]=false,cur[i]=Head[i];
	Deep[s]=0,vis[s]=true;
	queue<int>q;q.push(s);
	while(!q.empty()){
		int u=q.front();
		q.pop();vis[u]=false;
		for(int i=Head[u];i;i=Ed[i].Next){
			int v=Ed[i].To,w=Ed[i].Val;
			if(Deep[v]>Deep[u]+1&&w!=false){
				Deep[v]=Deep[u]+1;
				if(vis[v]==false){
					q.push(v);
					vis[v]=true;
				}
			}
		}
	}if(Deep[t]!=INF&&Deep[t]!=0) return true;
	 else return false;
}
inline int dfs(int u,int mi){
	int mm=0;
	if(u==t) return mi;
	for(int i=cur[u];i;i=Ed[i].Next){
		cur[u]=i;
		int v=Ed[i].To,w=Ed[i].Val;
		if(Deep[v]==Deep[u]+1&&w!=false){
			mm=dfs(v,min(w,mi));
			if(mm!=false){
				Ed[i].Val-=mm;
				Ed[i^1].Val+=mm;
				return mm;
			}
		}
	}return false;
}
inline int Dinic(){
	int ans=0,res=0;
	while(bfs()){
		while(res=dfs(s,INF)){
			ans+=res;
		}
	}
		
	return ans;
}
int r[M],c[M];
signed main(){
	scanf("%lld%lld",&m,&n);
	s=0,t=m+n+1;//关键在于建图 
	for(int i=1;i<=m;i++){
		scanf("%lld",&r[i]);
		Adde(s,i,r[i]);
		Adde(i,s,0);
		sum+=r[i];
	}
	for(int i=1;i<=n;i++){
		scanf("%lld",&c[i]);
		Adde(i+m,t,c[i]);
		Adde(t,i+m,0);
	}
	for(int i=1;i<=m;i++)
		for(int j=1;j<=n;j++)
			Adde(i,j+m,1),Adde(j+m,i,0);
	
	int maxx=Dinic();
	if(sum==maxx) cout<<1<<endl;
	else{
		cout<<0<<endl;
		return 0;
	}
	for(int i=1;i<=m;i++){
		for(int j=Head[i];j;j=Ed[j].Next){
			int v=Ed[j].To,w=Ed[j].Val;
			if(v>m&&w==false&&v<t)
				printf("%lld ",v-m);
		}
		cout<<'\n';
	}
	return 0;
} 

每个点拆成入点和出点,入点连超级原点,出点连超级汇点,跑Dinic,输出暴力的小trick

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define int long long
using namespace std;
const int M=2e5+110;
inline int read(){
	int sum=0,k=1;char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')k=-1;c=getchar();
	}while(c>='0'&&c<='9'){sum=sum*10+c-48;c=getchar();
	}return sum*k;
}
int Head[M],Tot=1;
struct Line_Node{
	int Next,To,Val;
}Ed[M];
inline void Adde(int u,int v,int w){
	Ed[++Tot]={Head[u],v,w};
	Head[u]=Tot;
}
int n,m,s,t,cur[M];
int Deep[M];bool vis[M];
inline bool bfs(){
	for(int i=0;i<=n*2+1;i++)	
		Deep[i]=INF,vis[i]=false,cur[i]=Head[i];
	Deep[s]=0,vis[s]=true;
	queue<int>q;q.push(s);
	while(!q.empty()){
		int u=q.front();
		q.pop();vis[u]=false;
		for(int i=Head[u];i;i=Ed[i].Next){
			int v=Ed[i].To,w=Ed[i].Val;
//			cout<<"u:"<<u<<" v:"<<v<<" w:"<<w<<" Deep[u]:"<<Deep[u]<<" Deep[v]:"<<Deep[v]<<endl;
			if(Deep[v]>Deep[u]+1&&w!=false){
				Deep[v]=Deep[u]+1;
				if(vis[v]==false){
					vis[v]=true,q.push(v);
				}
			}
		}
	}if(Deep[t]==INF) return false;
	else return true;
}
int tt[M],ff[M];
inline int dfs(int u,int mi){
//	cout<<"u:"<<u<<" mi:"<<mi<<endl;
 	int mm=0;
 	if(u==t) return mi;
 	for(int i=cur[u];i;i=Ed[i].Next){
 		cur[u]=i;
 		int v=Ed[i].To,w=Ed[i].Val;
// 		cout<<"v:"<<v<<" w:"<<w<<" Deep[u]:"<<Deep[u]<<" Deep[v]:"<<Deep[v]<<endl;
 		if(Deep[v]==Deep[u]+1&&w!=false){
 			mm=dfs(v,min(w,mi));
 			if(mm!=false){
 				tt[u]=v;
 				if(u!=s) ff[v-n]=true;
 				Ed[i].Val-=mm;
 				Ed[i^1].Val+=mm;
 				return mm;
			}
		}
	}return false;
}
inline int Dinic(){
	int ans=0,res=0;
	while(bfs()){
		while(res=dfs(s,INF)){
//			cout<<res<<endl;
			ans+=res;
		}
	}
	for(int i=1;i<=n;i++)
		if(!ff[i]){
			int u=i;
			cout<<u<<" ";
			while(tt[u]&&tt[u]!=t){
				cout<<tt[u]-n<<" ";
				u=tt[u]-n;
			}
			cout<<endl;
		}
	return ans;
}
int in[M],out[M];
bool chr[M];
inline void pr(int u){
	if(chr[u]) return ;
	chr[u]=1;
//	printf("%lld ",u);
	for(int i=Head[u];i;i=Ed[i].Next){
		int v=Ed[i].To,w=Ed[i^1].Val;
		if(v==s||v==t) continue;
		if(w!=false) return void(pr(v));
	}
}
signed main(){
	n=read(),m=read();
//	cout<<" n:"<<n<<" m:"<<m<<endl;
	s=0,t=n*2+1;
	for(int i=1;i<=n;i++)
		Adde(s,i,1),Adde(i+n,t,1),
		Adde(i,s,0),Adde(t,i+n,0);
	for(int i=1;i<=m;i++){
		int u=read(),v=read();
		Adde(u,v+n,1),Adde(v+n,u,0);
	}
	int maxx=Dinic();
//	for(int i=Head[0];i;i=Ed[i].Next){
//		int v=Ed[i].To,w=Ed[i^1].Val;
//		if(w!=false){
//			pr(v);
//			cout<<'\n';
//		}
//	}
	cout<<n-maxx<<endl;
	return 0;
} 
/*
1 4 7 10 11
2 5 8
3 6 9
*/
posted @ 2025-07-08 08:45  rerecloud  阅读(15)  评论(1)    收藏  举报