• BZOJ 1070: [SCOI2007]修车


    1070: [SCOI2007]修车

    Time Limit: 1 Sec  Memory Limit: 128 MB

    Submit: 6231  Solved: 2652

    [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)

    题解

    网络流题目。

    构图思路:将每个技术人员拆成n个点,(i,j)表示i员工倒数第j辆修的车,每辆车向这些点连边,表示i员工倒数第j辆修这辆车,流量为1,费用为i*x,x为该员工修这辆车的时间,乘i是因为倒数第i个修这辆车,那么对后i-1辆车都会多x的等待时间,会产生(i-1)*x的代价,所以总代价为i*x。

    源点向每辆车连边,流量为1,费用为0,每个点(i,j)向汇点连边,流量为1,费用为0。

    求最小费用最大流即可。

    代码

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<queue>
    using namespace std;
    const int N=65,M=10,inf=0x3f3f3f3f;
    int m,n,s,t,k,ans;
    int head[N*M],vis[N*M],dis[N*M],cur[N*M],from[N*M];
    struct edge{
    	int u,v,flow,cost,next;
    }e[N*N*M*4];
    void addedge(int u,int v,int flow,int cost){
    	e[k]=(edge){u,v,flow,cost,head[u]};
    	head[u]=k++;
    	e[k]=(edge){v,u,0,-cost,head[v]};
    	head[v]=k++;
    }
    queue<int>q;
    bool spfa(){
    	for(int i=s;i<=t;i++){
    		vis[i]=0;
    		dis[i]=inf;
    		from[i]=-1;
    	}
    	dis[s]=0;
    	q.push(s);
    	vis[s]=1;
    	int u,v,flow,cost;
    	while(!q.empty()){
    		u=q.front();
    		q.pop();
    		vis[u]=0;
    		for(int i=head[u];i!=-1;i=e[i].next){
    			v=e[i].v,flow=e[i].flow,cost=e[i].cost;
    			if(flow&&dis[u]+cost<dis[v]){
    				dis[v]=dis[u]+cost;
    				from[v]=i;
    				if(!vis[v]){
    					q.push(v);
    					vis[v]=1;
    				}
    			} 
    		}
    	}
    	if(dis[t]!=inf)return true;
    	return false;
    }
    void mcf(){
    	while(spfa()){
    		int x=inf;
    		for(int i=from[t];i!=-1;i=from[e[i].u])
    			x=min(x,e[i].flow);
    		for(int i=from[t];i!=-1;i=from[e[i].u]){
    			e[i].flow-=x;
    			e[i^1].flow+=x;
    			ans+=e[i].cost*x;
    		}
    	}
    }
    int main(){
    	memset(head,-1,sizeof(head));
    	scanf("%d%d",&m,&n);
    	s=0,t=n+n*m+1;
    	for(int i=1;i<=n;i++){
    		addedge(s,i,1,0);
    	}
    	for(int i=1;i<=m;i++){
    		for(int j=1;j<=n;j++){
    			addedge(i*n+j,t,1,0);
    		}
    	}
    	int x;
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=m;j++){
    			scanf("%d",&x);
    			for(int k=1;k<=n;k++){
    				addedge(i,j*n+k,1,x*k);
    			}
    		}
    	}
    	mcf();
    	printf("%.2lf
    ",(double)ans/n);
    	return 0;
    }
  • 相关阅读:
    [Android Studio] Android Studio底边栏选项不见了,如何调出来
    [Android Studio] Android Studio中查看类的继承关系
    [Android Studio] Android Studio如何提示函数用法
    [Android Studio] Android Studio如何查看branch列表及切换branch(转载)
    [Android Studio] Android Studio使用教程(二)
    [Android Studio] Android Studio使用教程(一)
    [Android Studio] Android Studio移除的Module如何恢复(转载)
    [Android Studio] Android Studio如何删除module(转载)
    [Linux] ubuntu下查看CHM的软件
    python 在Windows中描述路径时出现的问题
  • 原文地址:https://www.cnblogs.com/chezhongyang/p/7746060.html
Copyright © 2020-2023  润新知