• 【模板】最小费用最大流(动态开节点(待解决))


    修车车喽~

    P2053 [SCOI2007]修车

    注意建图的时候不仅要关注第$i$辆车给第$j$个人修,还要排是第几个修,所以干脆直接拆成$n*m$个点代表$i,j$,连向$k$次序点。边费用应该是后面$(n-k)辆的等待时间+这辆修的时间=(n-k+1)*a(当前这辆所需时间)$

    又背了一个板子叻!打卡完成今日任务!

    贴上以前的丑丑代码,略微修改。


    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define oo 2147483647
    using namespace std;
    #define ll long long 
    
    int m, n;
    
    const int N = 100005;
    const int M = 2000005;
    
    int s, t;
    ll stot = 1, tov[M], f[M], nex[M], h[N], w[M];
    
    void add ( int u, int v, int ff, int ww ) {
        tov[++stot] = v;
        f[stot] = ff;
        w[stot] = ww;
        nex[stot] = h[u];
        h[u] = stot;
        
        tov[++stot] = u;
        f[stot] = 0;
        w[stot] = -ww;
        nex[stot] = h[v];
        h[v] = stot;
    }
    
    ll mincost;
    double maxflow;
    ll vis[N], dis[N], preu[N], prei[N];
    queue < int > q;
    
    bool spfa ( ) {
        memset ( vis, 0, sizeof ( vis ) );
        memset ( dis, 127, sizeof ( dis ) );
        vis[s] = 1; q.push( s ); dis[s] = 0;
        while ( !q.empty( ) ) {
            int u = q.front ( ); vis[u] = 0;
            q.pop ( );
            for ( int i = h[u]; i; i = nex[i] ) {
                int v = tov[i];
                if ( dis[v] > dis[u] + w[i] && f[i] ) {
                    dis[v] = dis[u] + w[i];
                    preu[v] = u;
                    prei[v] = i; 
                    if ( !vis[v] ) {
                        vis[v] = 1;
                        q.push ( v );
                    }
                }
            }
        } 
        return dis[t] < oo;
    }
    
    void doge ( ) {
        ll u = t, delta = oo;
        while ( u != s ) {
            delta = min ( delta, f[prei[u]] );
            u = preu[u];
        }
        u = t;
        while ( u != s ) {
            int i = prei[u];
            f[i] -= delta;
            f[i^1] += delta;
            u = preu[u];
        }
        mincost += delta * dis[t];
        maxflow += delta;
    }
    
    int main ( ) {
        scanf ( "%d%d", &m, &n );
        s = 0, t = n*m+n+1;
        for ( int i = 1; i <= n; i ++ ) {
            for ( int j = 1; j <= m; j ++ ) {
                int a;
                scanf ( "%d", &a );
                for ( int k = 1; k <= n; k ++ )
                    add ( n*(j-1)+k, i+n*m, 1, (n-k+1) *a );
            }
        }
        for ( int i = 1; i <= m*n; i ++ )
            add ( s, i, 1, 0 );
        for ( int i = n*m+1; i <= n*m+n; i ++ )
            add ( i, t, 1, 0 );
        while ( spfa ( ) )
            doge ( );
        printf ( "%.2lf", 1.0*mincost/n );
        return 0;
    }

  • 相关阅读:
    用来验证字符串的规则引擎
    C++基本错误:
    web service传递stream二进制对象的解决方法
    安装EnterpriseLibrary4.1后遇到PresentationBuildTasks找不到的问题
    关于NHibernate示例程序QuickStart无法运行的问题
    关于iframe.document
    .NET下转换日期格式为中文大写
    History(历史)命令用法 15 例
    防火墙技术发展趋势浅析
    MIME类型大全
  • 原文地址:https://www.cnblogs.com/wans-caesar-02111007/p/13942642.html
Copyright © 2020-2023  润新知