网络流最小费用最大流(bzoj【1877】晨跑)

传送门

板子一波~~

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int n,m;
int fst[505];
int nxt[100005];
int v[100005];
int k[100005];
int cst[100005];
int b[505];
int d[505];
int cost;
int edge=1;
const int inf=1000000000;
int S=501,T=502;
void add(int x,int y,int val,int ct)
{
	edge++;
	nxt[edge]=fst[x];
	fst[x]=edge;
	v[edge]=y;
	k[edge]=val;
	cst[edge]=ct;
}
queue<int> q;
bool spfa()
{
	for(int i=0;i<=500;i++)
	d[i]=inf,b[i]=0;
	d[T]=inf;
	d[S]=0;
	q.push(S);
	while(!q.empty())
	{
		int x=q.front();
		q.pop();
		b[x]=0;
		for(int i=fst[x];i;i=nxt[i])
		{
			if(k[i]&&d[v[i]]>d[x]+cst[i])
			{
				d[v[i]]=d[x]+cst[i];
				if(!b[v[i]])b[v[i]]=1,q.push(v[i]);
			}
		}
	}
	return d[T]!=inf;
}
int dfs(int x,int val)
{
	if(x==T||!val)
	{
		cost+=d[T]*val;
		return val;
	}
	b[x]=1;
	int tmp=0;
	for(int i=fst[x];i;i=nxt[i])
	{
		if(!b[v[i]]&&d[v[i]]==d[x]+cst[i]&&k[i])
		{
			int flow=dfs(v[i],min(val,k[i]));
			val-=flow;
			k[i]-=flow;
			k[i^1]+=flow;
			tmp+=flow;
		}
		if(!val)break;
	}
	if(!tmp)d[x]=-1;
	return tmp;
}
int dinic()
{
	int tmp=0;
	while(spfa())tmp+=dfs(S,inf);
	return tmp;
}
int main()
{
	scanf("%d%d",&n,&m);
	add(1,1+n,inf,0);
	add(1+n,1,0,0);
	add(n,n+n,inf,0);
	add(n+n,n,0,0);
	for(int i=2;i<n;i++)
	{
		add(i,i+n,1,0);
		add(i+n,i,0,0);
	}
	int x,y,val;
	for(int i=1;i<=m;i++)
	{
	scanf("%d%d%d",&x,&y,&val);	
	add(x+n,y,1,val);
	add(y,x+n,0,-val);
	}
	add(S,1,inf,0);
	add(1,S,0,0);
	add(n+n,T,inf,0);
	add(T,n+n,0,0);
	printf("%d ",dinic());
	printf("%d",cost);
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/richard__luan/article/details/81010636
今日推荐