P3376 【模板】网络最大流Dinci

传送门:P3376 【模板】网络最大流
盯着洛谷OI爷的题解,我调了一个三个小时后,发现加个#define int long long就过了QAQ

vector邻接表

这是在白书抄的模板

//#pragma GCC optimize(2)
#include 
using namespace std;
#define ll long long
#define int long long
#define endl "\n"
const int MAX=1e4+7;
const unsigned ll inf=LLONG_MAX;
struct edge{
	ll to,cap,rev;
};
vector<edge>G[MAX];  //图的邻接表 
int level[MAX];  //顶点到源点的距离标号 
int iter[MAX];  //当前弧,在其之前的边已经没有用了

//有向图增加一条从from到to的容量为cap的边 
void add_edge(int from,int to,ll cap){
	G[from].push_back( (edge){to,cap,G[to].size()} );
	G[to].push_back( (edge){from,0,G[from].size()-1} ); 
} 

//通过bfs计算从源点出发的距离标号
void bfs(int s){
	memset(level,-1,sizeof(level));
	queue<int>que;
	level[s]=0;
	que.push(s);
	while(!que.empty()){
		int v=que.front(); que.pop();
		for(int i=0;i<G[v].size();i++){
			edge &e=G[v][i];
			if(e.cap>0&&level[e.to]<0){
				level[e.to]=level[v]+1;
				que.push(e.to);
			}
		}
	}
}

//通过dfs寻找增广路
int dfs(int v,int t,ll f){
	if(v==t)return f;
	for(int &i=iter[v];i<G[v].size();i++){
		edge &e=G[v][i];
		if(e.cap>0&&level[v]<level[e.to]){
			ll d=dfs(e.to,t,min(f,e.cap));
			if(d>0){
				e.cap-=d;
				G[e.to][e.rev].cap+=d;
				return d;
			}
		}
	}
	return 0; 
} 

//求解从s到t的最大流
int max_flow(int s,ll t){
	ll flow=0;
	while(1){
		bfs(s);
		if(level[t]<0)return flow;
		memset(iter,0,sizeof(iter));
		ll f=0;
		while((f= dfs(s,t,inf)) >0)flow+=f;
	}
	return flow;
}
 
signed main(){
    ios_base::sync_with_stdio(0);cin.tie(0),cout.tie(0);
	int n,m,s,t; //点、边、源点、汇点 
	cin>>n>>m>>s>>t;
	for(int i=0;i<m;i++){
		ll u,v,w;cin>>u>>v>>w;
		add_edge(u,v,w);
	}
	cout<<max_flow(s,t);
   return 0;
} 

head链式前向星

看别人代码自己修修改改凑合着用

//#pragma GCC optimize(2)
#include 
using namespace std;
#define ll long long
#define int long long
#define endl "\n"
const int MAX=1e4+7;
const ll inf=LLONG_MAX;
struct Edge{
	ll nxt,to,cap;
}edge[2*MAX];
int cnt=1; 
int level[MAX];  //顶点到源点的距离标号
int head[MAX],rad[MAX]; 
void add(int u,int v,int w){
	edge[++cnt].to=v;
	edge[cnt].cap=w;
	edge[cnt].nxt=head[u];
	head[u]=cnt;
}
//有向图增加一条从from到to的容量为cap的边 
void add_edge(int from,int to,ll cap){
	add(from,to,cap);
	add(to,from,0);  反向边
} 

//通过bfs计算从源点出发的距离标号
bool bfs(int s,int t){
	memset(level,0,sizeof(level));
	queue<int>que;
	level[s]=1;
	que.push(s);
	while(!que.empty()){
		int v=que.front(); que.pop();
		rad[v]=head[v];  //复原当前弧 
		for(int i=head[v];i;i=edge[i].nxt){
			Edge &e=edge[i];
			if(e.cap&&!level[e.to]){
				level[e.to]=level[v]+1;
				que.push(e.to);
			}
		}
	}
	return level[t]!=0;
}

//通过dfs寻找增广路
int dfs(int v,int t,ll flow){
	if(v==t)return flow;
	ll tmp=flow,k;
	for(int i=rad[v];i;i=edge[i].nxt){
		Edge &e=edge[i]; rad[v]=i;
		if(e.cap&&level[v]+1==level[e.to]){
			k=dfs(e.to,t,min(tmp,e.cap));
			edge[i].cap-=k;
			edge[i^1].cap+=k;  //反向边 
			tmp-=k;  
			if(!tmp)break;
		}
	}
	return flow-tmp; 
} 

//求解从s到t的最大流
ll Dinic(int s,int t){
	ll max_flow=0;
	while(bfs(s,t))
		max_flow+=dfs(s,t,inf);
	return max_flow;
}
 
signed main(){
    ios_base::sync_with_stdio(0);cin.tie(0),cout.tie(0);
	int n,m,s,t; //点、边、源点、汇点 
	cin>>n>>m>>s>>t;
	for(int i=1;i<=m;i++){
		int u,v,w;cin>>u>>v>>w;
		add_edge(u,v,w);
	}
	cout<<Dinic(s,t);
   return 0;
} 

你可能感兴趣的:(数据结构)