[BZOJ1061] [Noi2008]志愿者招募(费用流 / 单纯形)(未完成)

传送门


费用流来做这题真的很费劲啊(哭)不等式转建边什么的,不膜题解也太难了吧,但是这道题是单纯形裸题(可见高级算法的优越性
费用流的建图方法请去看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;
}

单纯形:

//正在学习

猜你喜欢

转载自blog.csdn.net/cabi_zgx/article/details/79610543