zoukankan      html  css  js  c++  java
  • BZOJ-1070 修车 最小费用最大流+拆点+略坑建图

    1070: [SCOI2007]修车
    Time Limit: 1 Sec Memory Limit: 162 MB
    Submit: 3624 Solved: 1452
    [Submit][Status][Discuss]

    Description
    同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。

    Input
    第一行有两个m,n,表示技术人员数与顾客数。 接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。

    Output
    最小平均等待时间,答案精确到小数点后2位。

    Sample Input
    2 2
    3 2
    1 4

    Sample Output
    1.50

    HINT
    数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)

    Source

    这个题啊,开始看出来是最小费用最大流了,但不知道怎么建图,人傻的不行,于是第一遍尝试WA告终
    

    借鉴了一下黄学长的建图姿势:
    把每个工人拆成N个点,一共N*M个点
    超级源S连这N*M个点,容量为1,费用为0
    超级汇T连N*M+(1~M)个点(车),容量为1,费用为0
    把每个车都与每个拆成的点相连,容量为1,费用为t【k】【i】*j

    很显然,每个工人同一时间只能洗一辆车,也只有一辆车能被洗,所以容量为0,至于费用,考虑第i个工人,他修第j辆车只对后面要修的车有影响,而前面修过的车已经对当前没有影响了。而这个影响就是后面每个将要修理的车都多等待了time的时间。
    然后zkw一遍除以人数即可。

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define inf 0x7fffffff
    int n,m;
    int pg[100][10];
    int S,T;
    struct data{
        int v,c,to,next;
    }edge[500010];
    int head[500010],cnt=1;
    int h,t,q[500010];
    int dis[500010];
    bool mark[500010],visit[500010];
    int ans;
    
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    void add(int u,int v,int cap,int cost)
    {
        cnt++;edge[cnt].v=cap;
        edge[cnt].to=v;edge[cnt].c=cost;
        edge[cnt].next=head[u];head[u]=cnt;
    }
    
    void insert(int u,int v,int cap,int cost)
    {
        add(u,v,cap,cost);add(v,u,0,-cost);
    }
    
    void init()
    {
        n=read();m=read();
        for (int i=1; i<=m; i++)
            for (int j=1; j<=n; j++)
                pg[i][j]=read();        
    }
    
    void make()
    {
        S=0,T=n*m+m+1;
        for (int i=1; i<=n*m; i++)
            insert(S,i,1,0);
        for (int i=n*m+1; i<=n*m+m; i++)
            insert(i,T,1,0);
        for (int i=1; i<=n; i++)
            for (int j=1; j<=m; j++)
                for (int k=1; k<=m; k++)
                    insert((i-1)*m+j,n*m+k,1,pg[k][i]*j);
    }
    
    bool spfa()
    {
        memset(visit,false,sizeof(visit));
        for (int i=S; i<=T; i++) dis[i]=inf;
        h=0,t=1;
        q[0]=T;visit[T]=1;dis[T]=0;
        while (h<t)
            {
                int now=q[h];h++;visit[now]=0;
                for (int i=head[now]; i; i=edge[i].next)
                    if (edge[i^1].v && dis[now]-edge[i].c<dis[edge[i].to])
                        {
                            dis[edge[i].to]=dis[now]-edge[i].c;
                            if (!visit[edge[i].to])
                                {
                                    visit[edge[i].to]=1;
                                    q[t++]=edge[i].to;
                                }
                        }
            }
        return dis[0]!=inf;
    }
    
    int dfs(int loc,int low)
    {
        mark[loc]=true;
        if (loc==T) return low;
        int w,used=0;
        for (int i=head[loc]; i; i=edge[i].next)
            if (dis[edge[i].to]==dis[loc]-edge[i].c && edge[i].v && !mark[edge[i].to])
                {
                    w=dfs(edge[i].to,min(low-used,edge[i].v));
                    ans+=w*edge[i].c;
                    edge[i].v-=w;edge[i^1].v+=w;
                    used+=w;if (used==low) return low;
                }
        return used;
    }
    
    void zkw()
    {
        int tmp=0;
        while (spfa())
            {
                mark[T]=1;
                while (mark[T])
                    {
                        memset(mark,0,sizeof(mark));
                        tmp+=dfs(0,inf);
                    }
            }
    }
    
    int main()
    {
        init();
        make();
        zkw();
        printf("%.2f
    ",(double)ans/m);
        return 0;
    }

    感谢DCrusher神犇,全程观赏水题过程。

  • 相关阅读:
    [jdk] JDK1.5新特性
    [maven] maven介绍
    [Ant] bulid.xml配置详解
    [spring] spring面试题
    .net(C#)时间相减、C#计算时间间隔
    如何记录应用程序日志
    交换机、集线器、路由器区别和使用浅谈
    ASP.NET 在域控制器上使用默认 ASPNET 帐户不能正常运行
    .NET 4中Entity Framework简介
    WCF传输性能测试
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5346225.html
Copyright © 2011-2022 走看看