zoukankan      html  css  js  c++  java
  • [SCOI2007] 修车

    Description

    (N(Nleq 60))辆车需要(M(Mleq 9))个人来修,第(i)个人修第(j)辆车花费的时间是(val[i][j]),每个人同一时间只能修一辆车。请求出顾客最小的平均等待时间、

    Solution

    假设第(i)个人修了(k)个车,顺序分别是(W_1,W_2,dots W_k),那么第(i)个人对等待时间的贡献就是(sumlimits_{i=1}^kW_i* imes (k+1-i))

    我们可以把人拆点,拆成一个二元组((i,j))表示第(i)个人正在修它的倒数第(j)辆车。为什么是倒数?只有倒数才能计算贡献,我们毕竟不知道这个人到底要修几辆车。但是第(i)个人修第(p)辆车且是这个人修的倒数第(k)辆时的贡献就是(val[i][p]*k)了。

    源点向每辆车连容量为1的边,代表一辆车只能修一次,每辆车向每个二元组连容量为1,费用为贡献的边,表示这个二元组修这辆车,最后每个二元组向汇点连容量为1的边点,代表每个二元组只能被使用一次。求一下费用流就好了~

    Code

    #include<set>
    #include<map>
    #include<queue>
    #include<cctype>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using std::min;
    using std::max;
    const int N=605;
    using std::swap;
    typedef double db;
    typedef long long ll;
    #define pb(A) push_back(A)
    #define pii std::pair<int,int>
    #define mp(A,B) std::make_pair(A,B)
    
    int n,m,s,t,cnt,val[63][12],ans;
    int head[N],in[N],dis[N],pre[N],a[N];
    
    struct Edge{
        int to,nxt,dis,flow;
    }edge[N*N];
    
    void add(int x,int y,int z,int p){
        edge[++cnt].to=y;
        edge[cnt].nxt=head[x];
        edge[cnt].flow=z;
        edge[cnt].dis=p;
        head[x]=cnt;
    }
    
    int getint(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch))w|=ch=='-',ch=getchar();
        while( isdigit(ch))X=X*10+ch-48,ch=getchar();
        return w?-X:X;
    }
    const int inf=1e9;
    bool spfa(){
        std::queue<int> q;q.push(s);
        memset(dis,0x3f,sizeof dis);dis[s]=0;
        memset(a,0,sizeof a);a[s]=inf;pre[s]=0;
        while(q.size()){
            int u=q.front();q.pop();in[u]=0;
            for(int i=head[u];i;i=edge[i].nxt){
                int to=edge[i].to;
                if(edge[i].flow and dis[to]>dis[u]+edge[i].dis){
                    dis[to]=dis[u]+edge[i].dis;
                    a[to]=min(a[u],edge[i].flow);
                    pre[to]=i;if(!in[to]) in[to]=1,q.push(to);
                }
            }
        }
        if(!a[t]) return 0;
        ans+=dis[t]*a[t];return 1;
    }
    
    void update(){
        for(int now=t;pre[now];now=edge[pre[now]^1].to)
            edge[pre[now]].flow-=a[t],edge[pre[now]^1].flow+=a[t];
    }
    
    signed main(){
        cnt=1;m=getint(),n=getint();
        s=0;t=n*m+n+1;
        for(int i=1;i<=n;i++){
            add(s,i,1,0);add(i,s,0,0);
            for(int j=1;j<=m;j++){
                val[i][j]=getint();
                for(int k=1;k<=n;k++)
                    add(i,n+(j-1)*n+k,1,val[i][j]*k),add(n+(j-1)*n+k,i,0,-val[i][j]*k);
            }
        }
        for(int i=1;i<=m*n;i++)
            add(i+n,t,1,0),add(t,i+n,0,0);
        while(spfa()) update();
        printf("%.2lf
    ",(db)ans/(db)n);
        return 0;
    }
    
    
  • 相关阅读:
    Zookeeper入门(三)之工作流
    Zookeeper入门(二)之基础
    Zookeeper入门(一)之概述
    Docker删除/停止容器
    webbench安装和简单使用
    Notepad++ 7.3.2 Download 64-bit x64 / 32-bit x86
    7 常见问题
    6 完整测试
    5 安装Alloc服务
    4 安装MPush
  • 原文地址:https://www.cnblogs.com/YoungNeal/p/9715249.html
Copyright © 2011-2022 走看看