[Luogu 2604] ZJOI2010 网络扩容

[Luogu 2604] ZJOI2010 网络扩容

<题目链接>


第一问直接最大流。

第二问,添加一遍带费用的边,边权 INF,超级源点连源点一条容量为 \(k\) 的边来限流,跑费用流。

大约是第一次用 namespace 封装,感觉还好。

#include <cstdio>
#include <cstring>
#include <queue>
using std::min;
using std::queue;
const int MAXN=1010,MAXM=10010,INF=0x3f3f3f3f;
int n,m,k,S,T,cnt,head[MAXN];
struct Edge
{
	int nxt,to,w,f;
	Edge(int nxt=0,int to=0,int w=0,int f=0):nxt(nxt),to(to),w(w),f(f){}
}e[MAXM<<1];
void AddEdge(int u,int v,int w,int f)
{
	e[++cnt]=Edge(head[u],v,w,f),head[u]=cnt;
}
void AddEdges(int u,int v,int w,int f)
{
	AddEdge(u,v,w,f),AddEdge(v,u,0,-f);
}
struct Query
{
	int u,v,c,w;
	void Init(void)
	{
		scanf("%d %d %d %d",&u,&v,&c,&w);
		AddEdges(u,v,c,0);
	}
	void Rebuild(void)
	{
		AddEdges(u,v,INF,w);
	}
}a[MAXM];
namespace MaxiumFlow
{
	static int dis[MAXN],cur[MAXN];
	bool BFS(void)
	{
		queue<int> q;
		memset(dis,0,sizeof dis);
		q.push(S),dis[S]=1;
		while(!q.empty())
		{
			int u=q.front();
			q.pop();
			for(int i=head[u],v;i;i=e[i].nxt)
				if(e[i].w && !dis[v=e[i].to])
					q.push(v),dis[v]=dis[u]+1;
		}
		return dis[T];
	}
	int DFS(int u,int k)
	{
		if(u==T || !k)
			return k;
		int sum=0;
		for(int i=cur[u],v,f;i;i=e[i].nxt)
			if(e[i].w && dis[v=e[i].to]==dis[u]+1 && (f=DFS(v,min(k,e[i].w))))
			{
				cur[u]=i;
				e[i].w-=f,e[((i-1)^1)+1].w+=f;
				k-=f,sum+=f;
			}
		if(!sum)
			dis[u]=0;
		return sum;
	}
	void Dinic(void)
	{
		int ans=0;
		while(BFS())
		{
			memcpy(cur,head,sizeof head);
			ans+=DFS(S,INF);
		}
		printf("%d ",ans);
	}
}
namespace MiniumCost
{
	static bool exist[MAXN];
	static int dis[MAXN],pre[MAXN],pre_e[MAXN],flow[MAXN];
	bool SPFA(void)
	{
		queue<int> q;
		memset(exist,0,sizeof exist);
		memset(dis,0x3f,sizeof dis);
		memset(pre,0,sizeof pre);
		memset(pre_e,0,sizeof pre_e);
		memset(flow,0x3f,sizeof flow);
		q.push(S),exist[S]=1,dis[S]=0;
		while(!q.empty())
		{
			int u=q.front();
			q.pop(),exist[u]=0;
			for(int i=head[u],v;i;i=e[i].nxt)
				if(e[i].w && dis[v=e[i].to]>dis[u]+e[i].f)
				{
					dis[v]=dis[u]+e[i].f;
					pre[v]=u,pre_e[v]=i;
					flow[v]=min(flow[u],e[i].w);
					if(!exist[v])
						q.push(v),exist[v]=1;
				}
		}
		return dis[T]^INF;
	}
	void MCMF(void)
	{
		int ans=0;
		while(SPFA())
			for(int i=T,t;i^S;i=pre[i])
			{
				e[t=pre_e[i]].w-=flow[T];
				e[((t-1)^1)+1].w+=flow[T];
				ans+=e[t].f*flow[T];
			}
		printf("%d\n",ans);
	}
}
int main(int argc,char *argv[])
{
	scanf("%d %d %d",&n,&m,&k);
	S=1,T=n;
	for(int i=1;i<=m;++i)
		a[i].Init();
	MaxiumFlow::Dinic();
	for(int i=1;i<=m;++i)
		a[i].Rebuild();
	AddEdges(--S,1,k,0);
	MiniumCost::MCMF();
	return 0;
}

谢谢阅读。

posted @ 2018-04-03 21:31  Capella  阅读(110)  评论(0编辑  收藏  举报

谢谢光临