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;
}

时间: 2024-10-12 02:25:17

BZOJ 1070 修车(费用流)的相关文章

BZOJ SCOI 2007 修车 费用流

题目大意:有一些车和一些修车的人,给出每个人修每个车的时间,问所有人等待的最短平均时间是多少. 思路:记得POJ有一个和这个很像的题,做法是一样的.对于每个人修车的时候,我们只考虑他修车的时间对在它之后修车的人的时间的影响,因此我们只要考虑每一辆车是倒数第几个修的就可以了,然后朴素的建图,跑朴素的费用流,就可以过. CODE: #include <queue> #include <cstdio> #include <cstring> #include <ioman

BZOJ 1070 修车(最小费用流)

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1070 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. 第一行有两个m,n,表示技术人员数与顾客数. 接下来n行,每行m个整数.第i+1行第j个数表示第j位技术人员维修第i

BZOJ 3130: [Sdoi2013]费用流 网络流+二分

3130: [Sdoi2013]费用流 Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 1230  Solved: 598[Submit][Status][Discuss] Description Alice和Bob在图论课程上学习了最大流和最小费用最大流的相关知识.     最大流问题:给定一张有向图表示运输网络,一个源点S和一个汇点T,每条边都有最大流量.一个合法的网络流方案必须满足:(1)每条边的实际流量都

BZOJ 1283 序列 费用流

题目大意:给定一个长度为n的序列,要求选一些数,使得任意一个长度为m个区间中最多选k个数,求最大的和 费用流直接跑就是了 把这个序列用流量为k费用为0的边连成一条直线 然后第i个点向第i+m个点连一条费用为a[i]流量为1的边 跑最大费用最大流即可 卡单纯型差评.... #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 1010 #d

[BZOJ1070] [SCOI2007] 修车 (费用流 &amp; 动态加边)

Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. Input 第一行有两个m,n,表示技术人员数与顾客数. 接下来n行,每行m个整数.第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T. Output 最小平均等待时间,答案精确到小数点后2位

bzoj 1070: [SCOI2007]修车 -- 费用流

1070: [SCOI2007]修车 Time Limit: 1 Sec  Memory Limit: 128 MB Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. Input 第一行有两个m,n,表示技术人员数与顾客数. 接下来n行,每行m个整数.第

bzoj 3130 [Sdoi2013]费用流(二分,最大流)

Description Alice和Bob在图论课程上学习了最大流和最小费用最大流的相关知识.    最大流问题:给定一张有向图表示运输网络,一个源点S和一个汇点T,每条边都有最大流量.一个合法的网络流方案必须满足:(1)每条边的实际流量都不超过其最大流量且非负:(2)除了源点S和汇点T之外,对于其余所有点,都满足该点总流入流量等于该点总流出流量:而S点的净流出流量等于T点的净流入流量,这个值也即该网络流方案的总运输量.最大流问题就是对于给定的运输网络,求总运输量最大的网络流方案.   上图表示

【SDOI 2013】【BZOJ 3130】费用流

这题的第一问是一个裸最大流,不多说了,关键在于第二问.首先有一个结论,Bob一定把费用加在一条边上,于是我们就可以二分每条边的流量,验证是否能得到最大流即可 code: #include<iostream> #include<cstdio> #include<cstring> #define inf 0x7fffffff using namespace std; int n,m,p,e,ei; int point[101],next[2001]; int cur[101

BZOJ 3130 [Sdoi2013]费用流 ——网络流

[题目分析] 很容易想到,可以把P放在流量最大的边上的时候最优. 所以二分网络流,判断什么时候可以达到最大流. 流量不一定是整数,所以需要实数二分,整数是会WA的. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> //#include <map> #include <set> #include <queue> #in