负载平衡问题
又混进来了奇怪的题???我一看这不就是糖果传递???一脸懵逼的我点开题解发现竟然可以MFMC!
不过糖果传递貌似是这个的加强版(雾)【明明可以线性贪心为什么要网络流!】
看了一下题解大概是这个样子滴。
1.相邻的仓库之间连(inf,1)
2.大于平均值连原点(ai-ave,0)
3.小于平均值连汇点(ave-ai,0)
然后跑MFMC就好了啊w
[写了一堆锅的MCMF...NOIP以后手太生了。。。]
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define mxn 110
#define mxm 11000
#define inf 20021225
using namespace std;
struct edge{int f,to,lt,c;}e[mxm<<4];
int in[mxn],s,t,cnt=1,nn,mm,n,m;
bool vis[mxn];int dis[mxn];
queue<int> que;
void addedge(int x,int y,int f,int c)
{
e[++cnt].to=y;e[cnt].lt=in[x];e[cnt].f=f;e[cnt].c=c;in[x]=cnt;
e[++cnt].to=x;e[cnt].lt=in[y];e[cnt].f=0;e[cnt].c=-c;in[y]=cnt;
}
bool spfa()
{
for(int i=1;i<=nn;i++) dis[i]=inf,vis[i]=0;
while(!que.empty()) que.pop();
vis[t]=1;dis[t]=0;que.push(t);
while(!que.empty())
{
int x=que.front();vis[x]=0;que.pop();//printf("QAQ");
for(int i=in[x];i;i=e[i].lt)
{
//printf("*");
if(e[i^1].f&&dis[e[i].to]>dis[x]+e[i^1].c)
{
dis[e[i].to]=dis[x]+e[i^1].c;
if(!vis[e[i].to]) que.push(e[i].to),vis[e[i].to]=1;
}
}
}
return dis[s]!=inf;
}
int ans;
int dfs(int x,int flow)
{
//printf("QAQ");
vis[x]=1;
if(x==t||!flow) return flow;
int cur=flow;
for(int i=in[x];i;i=e[i].lt)
{
int v=e[i].to;//printf("*");
if(dis[x]==dis[v]+e[i].c&&e[i].f&&!vis[v])
{
int tmp=dfs(v,min(e[i].f,cur));
e[i].f-=tmp;e[i^1].f+=tmp;cur-=tmp;
ans+=tmp*e[i].c;
if(!cur) return flow;
}
}
dis[x]=inf;
return flow-cur;
}
int a[mxn],ave;
void mcmf()
{
//int w;
while(spfa())
{
//printf("YYY");
vis[t]=1;
while(vis[t])
{
memset(vis,0,sizeof(vis));
dfs(s,inf);
}
}
}
int main()
{
scanf("%d",&n);
s=n+1;t=n+2;nn=t;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),ave+=a[i];
ave/=n;
for(int i=1;i<=n;i++)
{
if(a[i]>ave) addedge(s,i,a[i]-ave,0);
if(a[i]<ave) addedge(i,t,ave-a[i],0);
if(i==1) addedge(n,i,inf,1),addedge(i,n,inf,1);
else addedge(i-1,i,inf,1),addedge(i,i-1,inf,1);
}
mcmf();
printf("%d
",ans);
return 0;
}