zoukankan      html  css  js  c++  java
  • 数字梯形问题

    题目描述

    题解:

    分操作讨论一下。

    操作$1$:

    两条路径走到同一个点原地爆炸。

    由于要求点只能取一次,我们可以将点拆为入点和出点。

    1.入点->出点,容量为$1$,费用为点权相反数;

    2.上面的出点->下面的入点,容量为$1$,费用为0;

    3.$S$->最上面一排入点,最下面一排出点->$T$,处理和$2$操作是一样的。

    然后最大费用流。

    操作$2$:

    两条路径走到一条边上原地爆炸。

    由于边只能取一次,点都不用拆。

    上面点->下面点,容量为$1$,费用为下面点点权相反数。

    然后最大费用流。

    巨坑:两条路径可能相交于最下面的点,所以最下面一排->$T$的容量至少为$2$。

    操作$3$:

    瞎走。只要向下就不原地爆炸。

    没啥好说的,上面点->下面点,容量正无穷,费用为下面点点权相反数。

    然后最大费用流。

    代码:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 3200
    #define ll long long
    const int inf = 0x3f3f3f3f;
    const ll  Inf = 0x3f3f3f3f3f3f3f3fll;
    inline int rd()
    {
        int f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
        return f*c;
    }
    int n,m,S,T,hed[N],cnt=-1;
    int a[45][45];
    int _id(int x,int y)
    {
        return y+(x*(x-1)/2);
    }
    struct EG
    {
        int to,nxt;
        ll w,c;
    }e[60*N];
    void ae(int f,int t,ll w,ll c)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        e[cnt].w = w;
        e[cnt].c = c;
        hed[f] = cnt;
    }
    ll dep[N],fl[N];
    int pre[N],fa[N];
    bool vis[N];
    queue<int>q;
    bool spfa()
    {
        memset(dep,0x3f,sizeof(dep));
        dep[S] = 0,vis[S] = 1,fl[S] = Inf;q.push(S);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            for(int j=hed[u];~j;j=e[j].nxt)
            {
                int to = e[j].to;
                if(e[j].w&&dep[to]>dep[u]+e[j].c)
                {
                    dep[to] = dep[u] + e[j].c;
                    fl[to] = min(fl[u],e[j].w);
                    pre[to] = j,fa[to] = u;
                    if(!vis[to])
                    {
                        vis[to] = 1;
                        q.push(to);
                    }
                }
            }
            vis[u] = 0;
        }
        return dep[T]!=Inf;
    }
    ll mcmf()
    {
        ll ret = 0;
        while(spfa())
        {
            ret+=fl[T]*dep[T];
            int u = T;
            while(u!=S)
            {
                e[pre[u]].w-=fl[T];
                e[pre[u]^1].w+=fl[T];
                u = fa[u];
            }
        }
        return ret;
    }
    void init()
    {
        memset(hed,-1,sizeof(hed));
        cnt = -1,S = 0,T = 3000;
    }
    void Case1()
    {
        init();
        for(int i=1;i<=n;i++)
        {
            int x = _id(n,i);
            ae(S,x<<1,1,0);
            ae(x<<1,S,0,0);
        }
        for(int i=n;i<=n+m-1;i++)
            for(int j=1;j<=i;j++)
            {
                int x = _id(i,j);
                ae(x<<1,x<<1|1,1,-a[i][j]);
                ae(x<<1|1,x<<1,0,a[i][j]);
            }
        for(int i=n;i<n+m-1;i++)
            for(int j=1;j<=i;j++)
            {
                int x = _id(i,j);
                int y = _id(i+1,j);
                ae(x<<1|1,y<<1,1,0);
                ae(y<<1,x<<1|1,0,0);
                y = _id(i+1,j+1);
                ae(x<<1|1,y<<1,1,0);
                ae(y<<1,x<<1|1,0,0);
            }
        for(int i=1;i<=n+m-1;i++)
        {
            int x = _id(n+m-1,i);
            ae(x<<1|1,T,1,0);
            ae(T,x<<1|1,0,0);
        }
        printf("%lld
    ",-mcmf());
    }
    void Case2()
    {
        init();
        for(int i=1;i<=n;i++)
        {
            int x = _id(n,i);
            ae(S,x,1,-a[n][i]);
            ae(x,S,0,a[n][i]);
        }
        for(int i=n;i<n+m-1;i++)
            for(int j=1;j<=i;j++)
            {
                int x = _id(i,j);
                int y = _id(i+1,j);
                ae(x,y,1,-a[i+1][j]);
                ae(y,x,0,a[i+1][j]);
                y = _id(i+1,j+1);
                ae(x,y,1,-a[i+1][j+1]);
                ae(y,x,0,a[i+1][j+1]);
            }
        for(int i=1;i<=n+m-1;i++)
        {
            int x = _id(n+m-1,i);
            ae(x,T,Inf,0);
            ae(T,x,0,0);
        }
        printf("%lld
    ",-mcmf());
    }
    void Case3()
    {
        init();
        for(int i=1;i<=n;i++)
        {
            int x = _id(n,i);
            ae(S,x,1,-a[n][i]);
            ae(x,S,0,a[n][i]);
        }
        for(int i=n;i<n+m-1;i++)
            for(int j=1;j<=i;j++)
            {
                int x = _id(i,j);
                int y = _id(i+1,j);
                ae(x,y,Inf,-a[i+1][j]);
                ae(y,x,0,a[i+1][j]);
                y = _id(i+1,j+1);
                ae(x,y,Inf,-a[i+1][j+1]);
                ae(y,x,0,a[i+1][j+1]);
            }
        for(int i=1;i<=n+m-1;i++)
        {
            int x = _id(n+m-1,i);
            ae(x,T,Inf,0);
            ae(T,x,0,0);
        }
        printf("%lld
    ",-mcmf());
    }
    int main()
    {
    //    freopen("digit1.in","r",stdin);
        n = rd(),m = rd();
        for(int i=n;i<=n+m-1;i++)
            for(int j=1;j<=i;j++)
                a[i][j] = rd();
        Case1();
        Case2();
        Case3();
        return 0;
    }
  • 相关阅读:
    PHP做Web开发的MVC框架(Smarty使用说明 )
    PHP + Smarty + MySQL
    PHP中smarty与MYSQL数据库的连接
    linux上安装phpstudy
    ThinkPHP使用smarty模板引擎的方法
    smarty 模板几个例子(变量调节器)
    Smarty的基本使用与总结
    gcd 控制线程执行顺序(供参考)
    手动实现 NSTabViewController 的 Rect Transition 及 Propagate Title-b
    Mac、Linux与Windows
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10256644.html
Copyright © 2011-2022 走看看