zoukankan      html  css  js  c++  java
  • BZOJ 1070 修车(费用流)

    如果能想到费用流,这道题就是显然了。

    要求所有人的等待平均时间最小,也就是所有人的总等待时间最小。

    每辆车只需要修一次,所以s连每辆车容量为1,费用为0的边。 现在需要把每个人拆成n个点,把车和每个人的第k个点连一条容量为1,费用为cost[i][j]*k的边。

    最后把每个人拆完后的点向汇点连一条容量为1,费用为0的边。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define inf 0x7fffffff
    #define T 601
    using namespace std;
    int n,m,cnt=1,ans,t[61][10];
    int d[605],q[605],from[605],head[605];
    bool mark[605];
    struct edge{int from,to,next,c,v;}e[100001];
    void ins(int u,int v,int w,int c)
    {
        cnt++;
        e[cnt].from=u;e[cnt].to=v;
        e[cnt].next=head[u];head[u]=cnt;
        e[cnt].c=c;e[cnt].v=w;
    }
    void insert(int u,int v,int w,int c)
    {ins(u,v,w,c);ins(v,u,0,-c);}
    bool spfa()
    {
        memset(mark,0,sizeof(mark));
        for(int i=0;i<=T;i++)d[i]=inf;
        int t=0,w=1;
        d[T]=0;mark[T]=1;q[0]=T;
        while(t!=w)
        {
            int now=q[t];t++;if(t==T)t=0;
            for(int i=head[now];i;i=e[i].next)
                if(e[i^1].v&&d[e[i].to]>d[now]-e[i].c)
                {
                    d[e[i].to]=d[now]-e[i].c;
                    if(!mark[e[i].to])
                    {mark[e[i].to]=1;q[w++]=e[i].to;if(w==T)w=0;} 
                }
            mark[now]=0;    
        }
        if(d[0]==inf)return 0;
        return 1;
    }
    int dfs(int x,int f)
    {
        if(x==T){mark[T]=1;return f;}
        int used=0,w;
        mark[x]=1;
        for(int i=head[x];i;i=e[i].next)
            if(!mark[e[i].to]&&e[i].v&&d[x]-e[i].c==d[e[i].to])
            {
                w=f-used;
                w=dfs(e[i].to,min(e[i].v,w));
                ans+=w*e[i].c;
                e[i].v-=w;e[i^1].v+=w;
                used+=w;if(used==f)return f;
            }
        return used;
    }
    void zkw()
    {
        while(spfa())
        {
            mark[T]=1;
            while(mark[T])
            {
                memset(mark,0,sizeof(mark));
                dfs(0,inf);
            }
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                   scanf("%d",&t[i][j]);
        for(int i=1;i<=n*m;i++)
            insert(0,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,t[k][i]*j);
        zkw();
        printf("%.2lf",(double)ans/m);
        return 0;
    }
    View Code
  • 相关阅读:
    python 软件目录规范
    生成器与迭代器
    第四周-第08章节-Python3.5-装饰器
    第三周-第18章节-Python3.5-函数式编程与函数不同
    第三周-第17章节-Python3.5-递归
    第三周-第16章节-Python3.5-局部变量与全局变量作用域
    第三周-第14章节-Python3.5-函数式编程
    JAVA发红包案例
    JAVA字符串
    JAVA关于字符串&&字符数组处理的小题目
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6503147.html
Copyright © 2011-2022 走看看