1. 程式人生 > >網路流之模板

網路流之模板

dinic(二分圖中有優勢)

//codevs 1993
#include <cstdio>
#include <cstring>
#include <queue>
#define N 2000
#define INF 10000005
using namespace std;
int tot=-1,next[N*4+5],point[N*4+5],v[N*4+5],remind[N*4+5],cur[N*4+5],deep[N*4+5],n,m;
void addline(int x,int y,int cap)
{
	++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; remind[tot]=cap;
	++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x; remind[tot]=0;
}
bool bfs(int s,int t)
{
	int i;
	queue <int> q;
	q.push(s);
	memset(deep,0x7f,sizeof(deep));
    deep[s]=0;
    for (i=1;i<=m;i++)
      cur[i]=point[i];
    while (!q.empty())
    {
    	int x=q.front(); q.pop();
    	for (i=point[x];i!=-1;i=next[i])
    	  if (deep[v[i]]>INF && remind[i])
		{
    		q.push(v[i]); deep[v[i]]=deep[x]+1;
		}
	}
	return deep[t]<INF;
}
int dfs(int now,int t,int limit)
{
	if (now==t||!limit) return limit;
	int flow=0,f;
	for (int i=cur[now];i!=-1;i=next[i])
	  {
	  	cur[now]=i;
	  	if (deep[v[i]]==deep[now]+1 && (f=dfs(v[i],t,min(limit,remind[i]))))
	  	{
	  		flow+=f;
	  		limit-=f;
	  		remind[i]-=f;
	  		remind[i^1]+=f;
	  		if (!limit) break;
		  }
	  }
	return flow;
} 
int dinic(int s,int t)
{
	int ans=0;
	while (bfs(s,t))
	  ans+=dfs(s,t,INF);
	return ans;
}
int main()
{
	int i,a,b,cap;
	memset(next,-1,sizeof(next));
	memset(point,-1,sizeof(point));
	scanf("%d%d",&n,&m);
	for (i=1;i<=n;i++)
	{
		scanf("%d%d%d",&a,&b,&cap);
		addline(a,b,cap);
	}
	printf("%d",dinic(1,m));  	
}
isap(普通圖中有優勢)
#include <cstdio>
#include <cstring>
#include<iostream>
#include<cstring>
#include <queue>
#define N 2000
#define INF 10000005
using namespace std;
int tot=-1,next[N*4+5],point[N*4+5],v[N*4+5],remind[N*4+5],cur[N*4+5],deep[N*4+5],n,m,last[N*4+5],num[N*4+5],maxflow;
void addline(int x,int y,int cap)
{
	++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; remind[tot]=cap;
	++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x; remind[tot]=0;
}
void bfs(int t)
{
	queue<int>q;
	for (int i=1;i<=m;i++)
	  deep[i]=m;
	deep[t]=0;
	q.push(t);
	while (!q.empty())
	{
		int now=q.front(); q.pop();
		for (int i=point[now];i!=-1;i=next[i])
		  if (deep[v[i]]==m && remind[i^1])
		{
			deep[v[i]]=deep[now]+1;
			q.push(v[i]);
		}
	}
}
int addflow(int s,int t)
{
	int ans=INF,now=t;
	while (now!=s)
	{
		ans=min(ans,remind[last[now]]);
		now=v[last[now]^1];
	}
	now=t;
	while (now!=s)
	{
		remind[last[now]]-=ans;
		remind[last[now]^1]+=ans;
		now=v[last[now]^1];
	}
	return ans;
}
void isap(int s,int t)
{
	int now=s,i;
	bfs(t);
	for (i=1;i<=m;i++) ++num[deep[i]];
	for (i=1;i<=m;i++) cur[i]=point[i];
	while (deep[s]<m)
	{
      if (now==t)
      {
      	maxflow+=addflow(s,t);
      	now=s;
	  }
	  bool has_find=false;
	  for (int i=cur[now];i!=-1;i=next[i])
	  {
	  	int u=v[i];
	  	if (deep[u]+1==deep[now] && remind[i])
	  	{
	  		has_find=true;
	  		cur[now]=i;
	  		last[u]=i;
	  		now=u;
	  		break;
		  }
	  }
	  if (!has_find)
	  {
	  	int minn=m-1;
	  	for (int i=point[now];i!=-1;i=next[i])
	  	  if (remind[i])
	  	    minn=min(minn,deep[v[i]]);
	  	if (!(--num[deep[now]])) break;
	  	num[deep[now]=minn+1]++;
	  	cur[now]=point[now];
	  	if (now!=s) now=v[last[now]^1];
	  }
    }
}
int main()
{
	int i,a,b,cap;
	memset(next,-1,sizeof(next));
	memset(point,-1,sizeof(point));
	scanf("%d%d",&n,&m);
	for (i=1;i<=n;i++)
	{
		scanf("%d%d%d",&a,&b,&cap);
		addline(a,b,cap);
	}
	isap(1,m);
	printf("%d",maxflow);  	
}