首页 > 其他分享 >2022牛客多3 B 模拟费用流

2022牛客多3 B 模拟费用流

时间:2022-12-08 17:35:19浏览次数:89  
标签:11 费用 int rep 牛客 2022 include 模拟 define

B

题目很短,出的最小费用最大流。好像付费报名才能看。

当然不是裸题,是我也不会写,好久没写网络流了。

因为将图建出来边数为1e6 每次增广也是增广1流量 复杂度显然不能接受。

考虑模拟费用流来加快费用流的过程。同时这道题的退流情况简单所以可以人为模拟退流过程。

正确性:如果费用流正确 那么模拟费用流也正确。我不会证。

说一个我初始的想法:直接给每个城市分配够数量的人 然后不断交换两个城市的人来达到费用流的效果。

明显这不是一个费用流过程 同时会出现不对的情况没有实现真正的退流过程 所以这个贪心是错误的。

正解:考虑对每一个人来增广 增广时只需要交换的每个城市中的最小值即可,可以认为这是一个退流过程。

用堆来维护城市之间转移的最小值即可。这样大大降低了真正网络流时的情况数。

最后增广时和费用流增广几乎一模一样。

又理解了一遍模拟费用流。

code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 100000000
#define inf 100000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define P 1000000007ll
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define sq sqrt
#define y(w) t[w].y
#define x(w) t[w].x
#define z(w) t[w].z
#define id(cc) s[cc].id
#define F first
#define S second
#define mod 998244353
#define sc(A) scanf("%d",&A)
#define scs(A) scanf("%s",A);
#define put(A) printf("%d\n",A)
#define min(x,y) (x>=y?y:x)
#define max(x,y) (x>=y?x:y)
using namespace std;
const int MAXN=100010,maxn=1000010;
//模拟费用流
int n,k;
int E[MAXN],now[MAXN];
int c[MAXN][11],d[11],vis[11],last[11];
struct wy
{
	int x,id;
	friend bool operator <(wy a,wy b)
	{
		return a.x>b.x;
	}
};
priority_queue<wy> q[11][11];
int g[11][11];
int s[MAXN],t,h;
inline void top(int x,int y)
{
	wy w=q[x][y].top();
	while(now[w.id]!=x)
	{
		if(w.id==0)return;
		q[x][y].pop();
		w=q[x][y].top();
	}
	return;
}
int main()
{
	freopen("1.in","r",stdin);
	sc(n);sc(k);
	rep(1,k,i)sc(E[i]);
	rep(1,k,i)rep(1,k,j)
	if(i!=j)
	{
		q[i][j].push((wy){INF,0});
		g[i][j]=INF;
	}
	ll ans=0;
	rep(1,n,i)
	{
		t=h=0;
		rep(1,k,j){sc(c[i][j]);d[j]=c[i][j];s[++t]=j;vis[j]=1;last[j]=0;}
		while(++h<=t)
		{
			int x=s[h];
			vis[x]=0;
			rep(1,k,j)
			{
				if(x!=j&&d[x]+g[x][j]<d[j])
				{
					d[j]=d[x]+g[x][j];
					last[j]=x;
					if(!vis[j]){s[++t]=j;vis[j]=1;}
				}
			}
		}
		int w=0;
		rep(1,k,j)if(E[j]&&(w==0||d[j]<d[w]))w=j;
		ans+=d[w];
		--E[w];
		while(last[w])
		{
			int ww=last[w];
			wy cc=q[ww][w].top();
			now[cc.id]=w;
			rep(1,k,j)
			{
				if(j!=ww)top(ww,j),g[ww][j]=q[ww][j].top().x;
				if(j!=w)
				{
					q[w][j].push((wy){c[cc.id][j]-c[cc.id][w],cc.id});
					top(w,j);g[w][j]=q[w][j].top().x;
				}
			}
			w=last[w];
		}
		//i->w
		now[i]=w;
		rep(1,k,j)if(j!=w)
		{
			q[w][j].push((wy){c[i][j]-c[i][w],i});
			top(w,j);g[w][j]=q[w][j].top().x;
		}
	}
	putl(ans);
	return 0;
}

标签:11,费用,int,rep,牛客,2022,include,模拟,define
From: https://www.cnblogs.com/chdy/p/16966690.html

相关文章