HDU - 4280 Island Transport 双向图最大流

题目链接

https://vjudge.net/problem/HDU-4280

题意

n个城市,m道路,道路有最大通行量,是双向通行的,求最西边城市到最东边城市最大通行量

思路

裸的最大流,坐标没必要存,记录一下源汇点就行了。

注意道路是双向的,所以建边要双向建边,本来增广路算法反向容量0的边就不用再建了。

附了两份代码,Dinic 7.6s,ISAP 3.2s。

代码

//Dinic
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<string>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib> 
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
using namespace std;
	typedef long long ll;
	const int inf=0x3f3f3f3f;
	const int maxn=110010;
	const int maxe=210010;

	int head[maxn],cnt;
	struct Edge{
    
    
		int v;
		int w;
		int next;
	}edge[maxe];
	int n,n1,n2,m,k,s,t;
	ll maxflow;
	int deep[maxn];
	int now[maxe];


	void init(){
    
    
		memset(head,-1,sizeof(head));
		cnt=0;
		maxflow=0; 
		return ;	
	}
	void add(int u,int v,int w){
    
    
	//	cout<<u<<" "<<v<<" "<<w<<endl;
  		edge[cnt].v=v;
		edge[cnt].w=w;
		edge[cnt].next=head[u];
		head[u]=cnt++;
	}

	inline bool bfs(){
    
    
    	memset(deep,0x3f,sizeof(deep));
    	queue<int>q;
    	q.push(s);deep[s] = 0;now[s] = head[s];
    	while(q.size()){
    
    
        	int x = q.front();q.pop();
        	for(int i=head[x];i!=-1;i=edge[i].next){
    
    
        	    int y=edge[i].v;
         	    if(edge[i].w>0&&deep[y]==inf){
    
    
         	    	q.push(y);
        	        now[y]=head[y];
         	       	deep[y]=deep[x]+1;
        	        if(y==t)	return 1;
				}
        	}
    	}
    	return 0;
	}


	ll dfs(int x,int flow){
    
    
    	if(x==t)	return flow;
    	ll ans = 0,k,i;
    	for(i=now[x];i!=-1&&flow;i=edge[i].next){
    
    
        	now[x]=i;
        	int y=edge[i].v;
        	if(edge[i].w>0&&(deep[y]==deep[x]+1)){
    
    
        	    k=dfs(y,min(flow,edge[i].w));
         		if(!k)	deep[y]=inf;
            	edge[i].w-=k;
            	edge[i^1].w+=k;
            	ans+=k;
            	flow-=k;
        	}
    	}
    	return ans;
	}	

	void dinic(){
    
    
    	while(bfs())
    	    maxflow+=dfs(s,inf);
	}

	int main(){
    
    
		IOS
		int tn;
		cin>>tn;
		while(tn--){
    
    
			init();
			cin>>n>>m;
			int mi=inf,ma=-inf;
			for(int i=1;i<=n;i++){
    
    
				int x,y;
				cin>>x>>y;
				if(x<mi){
    
    
					mi=x;
					s=i;
				}
				if(x>ma){
    
    
					ma=x;
					t=i;
				}
			}
			while(m--){
    
    
				int u,v,w;
				cin>>u>>v>>w;
				add(u,v,w);
				add(v,u,w);
			}
			dinic();
			cout<<maxflow<<endl;
		}
    	return 0;
	}
//ISAP
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>  
#define endl "\n"
using namespace std;
	typedef long long ll;
	const int maxn=100050;
	const int maxe=200050;
	const int inf=0x3f3f3f3f;
	struct Edge{
    
    
		int v;
		int w;
		int next;
	}edge[maxe];
	int head[maxn],cnt;
	int gap[maxn],last[maxn],dis[maxn];
	int n,m;
		
	void add(int u,int v,int w){
    
    
		edge[cnt].next=head[u]; edge[cnt].v=v; edge[cnt].w=w; head[u]=cnt++;
	}
	void init(){
    
    
		cnt=0;
		memset(head,-1,sizeof(head));
	}
	void init_mf(int s,int t){
    
    
		memset(gap,0,sizeof(gap));
		memset(dis,0,sizeof(dis));
		++gap[dis[t]=1];
		for(int i=1;i<=n;i++) last[i]=head[i];
		queue<int>q; q.push(t);
		while(q.size()){
    
    
			int x=q.front();q.pop();
			for (int i=head[x];i!=-1;i=edge[i].next){
    
    
				int v=edge[i].v;
				if (!dis[v]) {
    
    
					++gap[dis[v]=dis[x]+1];
					q.push(v);
				}
			}
		}
	}


	ll aug(int x,int s,int t,int mi){
    
    
		if (x==t) return mi;
		ll flow=0;
		for (int &i=last[x];i!=-1;i=edge[i].next){
    
    
			int v=edge[i].v;
			if (dis[x]==dis[v]+1){
    
    
				ll tmp=aug(v,s,t,min(mi,edge[i].w));
				flow+=tmp,mi-=tmp,edge[i].w-=tmp,edge[i^1].w+=tmp;
				if (!mi) return flow;
			}
		}
		if (!(--gap[dis[x]])) 	dis[s]=n+1;
		++gap[++dis[x]],last[x]=head[x];
		return flow;
	}
	ll maxflow(int s,int t){
    
    
		init_mf(s,t);
		ll ret=aug(s,s,t,inf);
		while (dis[s]<=n)	ret+=aug(s,s,t,inf);
		return ret;
	}
	int main() {
    
    
		int tn;
		scanf("%d",&tn);
		while(tn--){
    
    
			int s,t;
			scanf("%d%d",&n,&m); 
			init();
			int mi=inf,ma=-inf;
			for(int i=1;i<=n;i++){
    
    
				int x,y;
				scanf("%d%d",&x,&y);
				if(x<mi){
    
    
					mi=x;
					s=i;
				}
				if(x>ma){
    
    
					ma=x;
					t=i;
				}
			}
			while(m--){
    
    
				int u,v,w;
				scanf("%d%d%d",&u,&v,&w);
				add(u,v,w);
				add(v,u,w);
			}
			printf("%lld\n",maxflow(s,t));
		}
		return 0;
	}

猜你喜欢

转载自blog.csdn.net/TheSunspot/article/details/108282009
今日推荐