网络流

最大流

void addedge(int x,int y,int v)
{
	tot++;
	edge[tot]=EDGE(y, t[x], v, tot+1);
	t[x]=tot;
	tot++;
	edge[tot]=EDGE(x, t[y], 0, tot-1);
	t[y]=tot;
} 
int bfs()
{
	for(int i=s;i<=e;i++)	vist[i]=0;
	que[1]=s;	vist[s]=1;
	int head=0,tail=1;
	while(head<tail)
	{
		head++;
		int x=que[head];
		for(int p=t[x];p>0;p=edge[p].nxt)
		{
			int y=edge[p].to;
			if(edge[p].v>0&&!vist[y])
			{
				vist[y]=vist[x]+1;
				que[++tail]=y;
			}
		}
	} 
	return vist[e];
} 
int dfs(int x,int f)
{
	if(x==e||!f)	return f;
	int sumf=0;
	for(int p=t[x];p>0;p=edge[p].nxt)
	{
		int y=edge[p].to;
		if(vist[y]==vist[x]+1&&edge[p].v>0)
		{
			int flow=dfs(y,min(f,edge[p].v));
			edge[p].v-=flow;
			edge[edge[p].re].v+=flow;
			f-=flow;
			sumf+=flow;
			if(!f)	break;
		}
	}
	return sumf;
} 
int dinic()
{
	int ans=0;
	while(bfs())	{	ans+=dfs(s,inf);	}
	return ans;
}

费用流

struct EDGE{
	int to, nxt, re, v, u;
	LL c;
	EDGE(){}
	EDGE(int a, int b, int d, int e, int f, LL g)
	{	to = a;	nxt = b; v = d; u = e; re = f; c = g;}
}edge[M];
int t[N], pre[N], pree[N], vist[N];
LL dist[N];
int tot;
LL cost;
queue<int>que;
void memclear()
{
	tot = 0;
	memset(t, 0, sizeof(t));
}
void addedge(int x,int y,int v, LL c)
{
	tot++;
	edge[tot]=EDGE(y, t[x], v, 0, tot+1, c);
	t[x]=tot;
	tot++;
	edge[tot]=EDGE(x, t[y], 0, 0, tot-1, -c);
	t[y]=tot;
} 
int spfa(int S, int E)
{
	for(int i=1;i<=E;i++)	dist[i]=inf;
	dist[0]=0;	que.push(0);	vist[0]=1;
	while(que.empty() == 0)
	{
		int x=que.front();
		que.pop();
		for(int p=t[x];p>0;p=edge[p].nxt)
		{
			int y=edge[p].to;
			if(edge[p].v>edge[p].u&&dist[y]>dist[x]+edge[p].c)
			{
				dist[y]=dist[x]+edge[p].c;
				pree[y]=p;	pre[y]=x;
				if(vist[y]==0)
				{
					vist[y]=1;
					que.push(y);
				 } 
			 } 
		}
		vist[x]=0;
	}
	return (dist[E]<inf);
}
void update(int S, int E)
{
	LL maxa=1e9 + 7;
	int x=E;
	while(x != S)
	{
		int p=pree[x];
		maxa=min(maxa,(LL)edge[p].v-edge[p].u);
		x=pre[x];	
	} 
	x=E;
	while(x != S)
	{
		int p=pree[x];
		cost+=maxa*edge[p].c;
		edge[p].u+=maxa;	edge[edge[p].re].u-=maxa;
		x=pre[x];
	}
} 
void solve(int S, int E, int n)
{
	cost = 0;
	for(int i = 1;i <= n; i++)
	{
		spfa(S, E);
		update(S, E);
		cout<<cost;
		if(i != n)
			cout<<" ";
	}
	cout<<endl;
}

最大费用可行流

//注意可能需要判环的情况

struct EDGE{
	int to, nxt, re, v, u;
	LL c;
	EDGE(int a = 0, int b = 0, int d = 0, int e = 0, int f = 0, LL g = 0)
	{	to = a;	nxt = b; v = d; u = e; re = f; c = g;}
}edge[M];
int t[N], pre[N], pree[N], vist[N];
LL dist[N];
int tot;
LL cost;
queue<int>que;
void memclear(int S, int E)
{
	for(int i = S; i <= E; i++)
		t[i] = 0;
	tot = 0; cost = 0;
}
void addedge(int x,int y,int v, LL c)
{
	tot++;
	edge[tot]=EDGE(y, t[x], v, 0, tot+1, c);
	t[x]=tot;
	tot++;
	edge[tot]=EDGE(x, t[y], 0, 0, tot-1, -c);
	t[y]=tot;
} 
int spfa(int S, int E)
{
	for(int i = 1;i <= E;i++)	dist[i] = inf;
	dist[S] = 0;	que.push(0);	vist[0] = 1;
	while(que.empty() == 0)
	{
		int x = que.front();
		que.pop();
		for(int p = t[x]; p > 0; p = edge[p].nxt)
		{
			int y = edge[p].to;
			if(edge[p].v > edge[p].u && dist[y] > dist[x] + edge[p].c)
			{
				dist[y] = dist[x] + edge[p].c;
				pree[y] = p;	pre[y] = x;
				if(vist[y] == 0)
				{
					vist[y] = 1;
					que.push(y);
				 } 
			 } 
		}
		vist[x] = 0;
	}
	return (dist[E] <= 0);
}
void update(int S, int E)
{
	LL maxa = inf;
	int x = E;
	while(x != S)
	{
		int p = pree[x];
		maxa = min(maxa,(LL)edge[p].v-edge[p].u);
		x = pre[x];	
	} 
	x = E;
	while(x != S)
	{
		int p = pree[x];
		cost += maxa*edge[p].c;
		edge[p].u += maxa;	edge[edge[p].re].u -= maxa;
		x = pre[x];
	}
} 
int main()
{
	int n, m;
	while(scanf("%d%d", &n, &m) != EOF)
	{
		int S = 0;
		int E = n + 1;
		memclear(S, E);
		for(int i = 1; i <= n; i++)
		{
			int a, b, c, d;
			scanf("%d%d%d%d", &a, &b, &c, &d);
			addedge(S, i, b, a);
			addedge(i, E, d, -c);
		}
		for(int i = 1; i <= m; i++)
		{
			int x, y, v;
			scanf("%d%d%d", &x, &y, &v);
			addedge(x, y, inf, v);
			addedge(y, x, inf, v); 
		}
		while(spfa(S, E))
			update(S, E);
		cout<<-cost<<endl; 
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值