重庆人民真幸福,分金币这样的题都敢考。
网络流24题原题。
貌似一群人做成数论。
一个点拆成两个点,连INF的边,费用为1。
S向入连原值减平均值为正的边,费用为0
出向T连原值减平均值为负的边,费用为0。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<queue>
const int INF=0x3f3f3f3f;
using namespace std;
struct Front_star{
int u,v,w,c,nxt;
}e[20001];
int cnt=1;
int first[20001]={0};
void addedge(int u,int v,int w,int c){
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].w=w;
e[cnt].c=c;
e[cnt].nxt=first[u];
first[u]=cnt;
}
void add(int u,int v,int w,int c){
addedge(u,v,w,c);
addedge(v,u,0,-c);
}
int a[1001]={0};
int balance=0;
int n;
int S=0;
int T=501;
int inqueue[501]={0};
int dis[501]={0};
int pre[501]={0};
int SPFA(){
queue<int> q;
for(int i=S;i<=T;i++){
dis[i]=INF;
}
dis[S]=0;
q.push(S);
while(!q.empty()){
int x=q.front();
q.pop();
inqueue[x]=0;
for(int i=first[x];i;i=e[i].nxt){
int v=e[i].v;
if(dis[v]>e[i].c+dis[x]&&e[i].w){
dis[v]=e[i].c+dis[x];
pre[v]=i;
if(!inqueue[v]){
q.push(v);
inqueue[v]=1;
}
}
}
}
return dis[T]!=INF;
}
void MCMF(){
int ans=0;
while(SPFA()){
int s=INF;
for(int i=pre[T];i;i=pre[e[i^1].v]){
s=min(s,e[i].w);
}
for(int i=pre[T];i;i=pre[e[i^1].v]){
e[i].w-=s;
e[i^1].w+=s;
}
ans+=dis[T]*s;
}
cout<<ans;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
balance+=a[i];
}
balance/=n;
for(int i=1;i<=n;i++){
if(a[i]-balance>0){
add(S,i,a[i]-balance,0);
}
else{
add(i+n,T,balance-a[i],0);
}
}
for(int i=2;i<=n-1;i++){
add(i,i-1,INF,1);
add(i,i-1+n,INF,1);
add(i,i+1,INF,1);
add(i,i+n+1,INF,1);
}
add(1,2,INF,1);
add(1,2+n,INF,1);
add(1,n,INF,1);
add(1,n+n,INF,1);
add(n,n-1,INF,1);
add(n,2*n-1,INF,1);
add(n,1,INF,1);
add(n,n+1,INF,1);
MCMF();
return 0;
}
原理:表示这个人还有多少钱可以浪。
up,貌似这个算法是错的。。。
这个可以跑结论
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define M 100005
using namespace std;
int a[M],s[M],n;
int main()
{
scanf("%d",&n);
int ave=0;
for (int i=1;i<=n;i++)
scanf("%d",&a[i]),ave+=a[i];
ave/=n;
for (int i=1;i<=n;i++)
s[i]=s[i-1]+a[i]-ave;
sort(s+1,s+1+n);
long long ans=0;
for (int i=1;i<=n;i++)
ans=ans+abs(s[i]-s[(n+1)/2]);
printf("%lld\n",ans);
return 0;
}