费用流来做这题真的很费劲啊(哭)不等式转建边什么的,不膜题解也太难了吧,但是这道题是单纯形裸题(可见高级算法的优越性
费用流的建图方法请去看byvoid的题解,太神啦!
单纯形我还在学,学完写吧!
费用流:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int INF=999999999;
struct node
{
int x,y,c,d,next,other;
}a[51000]; int len,last[11000];
int st,ed;
int n,m,ans;
void ins(int x,int y,int c,int d)
{
int k1,k2;
len++; k1=len;
a[len].x=x;a[len].y=y;a[len].c=c;a[len].d=d;
a[len].next=last[x];last[x]=len;
len++; k2=len;
a[len].x=y;a[len].y=x;a[len].c=0;a[len].d=-d;
a[len].next=last[y];last[y]=len;
a[k1].other=k2;
a[k2].other=k1;
}
int pre[51000],preg[51000];
int list[51000],head,tail;
int d[11000];
bool v[11000];
int c[11000];
bool spfa()
{
for(int i=1;i<=n+2;i++) c[i]=d[i]=INF;
d[st]=0; c[st]=INF;
memset(v,false,sizeof(v)); v[st]=true;
head=1,tail=2;list[head]=st;
while(head!=tail)
{
int x=list[head];
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(a[k].c>0 && d[y]>d[x]+a[k].d)
{
d[y]=d[x]+a[k].d;
pre[y]=k; preg[y]=x;
c[y]=min(c[x],a[k].c);
if(v[y]==false)
{
v[y]=true;
list[tail++]=y; if(tail==ed+1) tail=1;
}
}
}
head++; if(head==ed+1) head=1;
v[x]=false;
}
if(d[ed]==INF) return false;
ans+=d[ed]*c[ed];
for(int i=ed;i!=st;i=preg[i])
{
a[pre[i]].c-=c[ed];
a[a[pre[i]].other].c+=c[ed];
}
return true;
}
int p[11000];
int main()
{
//freopen("employee.in","r",stdin);
//freopen("employee.out","w",stdout);
scanf("%d%d",&n,&m);
memset(last,0,sizeof(last)); len=0;
st=0,ed=n+2;
for(int i=1;i<=n;i++) scanf("%d",&p[i]);
for(int i=1;i<=m;i++)
{
int x,y,d;
scanf("%d%d%d",&x,&y,&d);
ins(x,y+1,INF,d);//X[i]
}
int tmp;p[0]=0,p[n+1]=0;
for(int i=1;i<=n+1;i++)
{
tmp=p[i]-p[i-1];
if(i>1) ins(i,i-1,INF,0);//Y[i]
if(tmp>=0) ins(st,i,tmp,0);//c
else ins(i,ed,-tmp,0);//-c
}
int i=0; ans=0;
while(spfa()) i++;
printf("%d\n",ans);
return 0;
}
单纯形:
//正在学习