首页 > 代码库 > Bzoj1070 [SCOI2007]修车

Bzoj1070 [SCOI2007]修车

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 5325  Solved: 2217

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

 

网络流 费用流

……这题怎么这么像网络流?(悄悄百度)真是网络流啊………

 

把每个工人拆成n个点,这n个点分别向T连边,容量为1(同一时刻只能修一辆车),第i个点费用为i*(读入的花费)。

  ↑第i个点表示工人倒数第i个修这辆车,对总时间的贡献为等待的人数i*花费时间

 

跑费用流即可

 1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 #include<queue> 9 using namespace std;10 const int mxn=1010;11 int read(){12     int x=0,f=1;char ch=getchar();13     while(ch<0 || ch>9){if(ch==-)f=-1;ch=getchar();}14     while(ch>=0 && ch<=9){x=x*10+ch-0;ch=getchar();}15     return x*f;16 }17 struct edge{18     int u,v,nxt,f,w;19 }e[mxn*100];20 int hd[mxn],mct=1;21 void add_edge(int u,int v,int f,int w){22     e[++mct].v=v;23     e[mct].u=u;24     e[mct].nxt=hd[u];25     e[mct].f=f;e[mct].w=w;26     hd[u]=mct;return;27 }28 void insert(int u,int v,int f,int w){29     add_edge(u,v,f,w); add_edge(v,u,0,-w);return;30 }31 int S,T;32 int dis[mxn],pre[mxn];33 int n,m;34 queue<int>q;35 bool inq[mxn];36 void SPFA(int s){37     memset(dis,0x3f,sizeof dis);38     memset(pre,-1,sizeof pre);39     dis[s]=0;q.push(s);inq[s]=1;40     while(!q.empty()){41         int u=q.front();q.pop();inq[u]=0;42         for(int i=hd[u];i;i=e[i].nxt){43             int v=e[i].v;44             if(e[i].f && dis[v]>dis[u]+e[i].w){45                 dis[v]=dis[u]+e[i].w;46                 pre[v]=i;47                 if(!inq[v]){48                     inq[v]=1;49                     q.push(v);50                 }51             }52         }53     }54     return;55 }56 int mxflow(int s,int t){57     SPFA(s);58     int res=0;59     while(pre[t]!=-1){60         int tmp=0x3f3f3f3f;61         for(int i=pre[t];i!=-1;i=pre[e[i].u]){62             tmp=min(tmp,e[i].f);63         }64         res+=dis[t]*tmp;65         for(int i=pre[t];i!=-1;i=pre[e[i].u]){66             e[i].f-=tmp;67             e[i^1].f+=tmp;68         }69         SPFA(s);70     }71     return res;72 }73 int main(){74     int i,j,w;75     m=read();n=read();76     S=0;T=n+m*n+1;77     for(i=1;i<=n;i++){78         insert(S,i,1,0);79     }80     for(i=1;i<=n;i++){81         for(j=1;j<=m;j++){82             w=read();83             for(int k=1;k<=n;k++){84                 insert(i,j+n+m*(k-1),1,w*k);85             }86         }87     }88     for(i=1;i<=m;i++)89         for(j=1;j<=n;j++)90             insert(i+n+m*(j-1),T,1,0);91     int ans=mxflow(S,T);92 //    printf("!! %d\n",ans);93     printf("%.2f\n",(double)ans/n);94     return 0;95 }

 

 

上面那个跑了1000+ms,一看排行榜震惊了,怎么前面全是几十ms跑完的

 

在黄学长博客看到了神奇的zkw费用流,(看上去像是Dinic和SPFA的结合体),学习一下↓

这样写快了一半。

然而还是不知道几十ms怎么做到的啊

  1 /*by SilverN*/  2 #include<algorithm>  3 #include<iostream>  4 #include<cstring>  5 #include<cstdio>  6 #include<cmath>  7 #include<vector>  8 #include<queue>  9 using namespace std; 10 const int mxn=1010; 11 int read(){ 12     int x=0,f=1;char ch=getchar(); 13     while(ch<0 || ch>9){if(ch==-)f=-1;ch=getchar();} 14     while(ch>=0 && ch<=9){x=x*10+ch-0;ch=getchar();} 15     return x*f; 16 } 17 struct edge{ 18     int u,v,nxt,f,w; 19 }e[mxn*100]; 20 int hd[mxn],mct=1; 21 void add_edge(int u,int v,int f,int w){ 22     e[++mct].v=v; 23     e[mct].u=u; 24     e[mct].nxt=hd[u]; 25     e[mct].f=f;e[mct].w=w; 26     hd[u]=mct;return; 27 } 28 void insert(int u,int v,int f,int w){ 29     add_edge(u,v,f,w); add_edge(v,u,0,-w);return; 30 } 31 int S,T; 32 int dis[mxn],pre[mxn]; 33 int n,m; 34 queue<int>q; 35 bool inq[mxn]; 36 bool mark[mxn]; 37 bool SPFA(int s){ 38     memset(inq,0,sizeof inq); 39     for(int i=0;i<=T;i++)dis[i]=0x3f3f3f3f; 40     dis[T]=0;q.push(T);inq[T]=1; 41     while(!q.empty()){ 42         int u=q.front();q.pop();inq[u]=0; 43         for(int i=hd[u];i;i=e[i].nxt){ 44             int v=e[i].v; 45             if(e[i^1].f && dis[v]>dis[u]-e[i].w){ 46                 dis[v]=dis[u]-e[i].w; 47 //                pre[v]=i; 48                 if(!inq[v]){ 49                     inq[v]=1; 50                     q.push(v); 51                 } 52             } 53         } 54     } 55     if(dis[S]==0x3f3f3f3f)return 0; 56     return 1; 57 } 58 int ans=0; 59 int DFS(int x,int f){ 60     if(x==T){inq[T]=1;return f;} 61     int used=0,w; 62     inq[x]=1; 63     for(int i=hd[x];i;i=e[i].nxt){ 64         int v=e[i].v; 65         if(!inq[v] && e[i].f && dis[x]-e[i].w==dis[v]){ 66             w=f-used; 67             w=DFS(v,min(e[i].f,w)); 68             ans+=w*e[i].w; 69             e[i].f-=w;    e[i^1].f+=w; 70             used+=w; 71             if(used==f)return f; 72         } 73     } 74     return used; 75 } 76  77 void mxflow(int s,int t){ 78     while(SPFA(s)){ 79         inq[T]=1; 80         while(inq[T]){ 81             memset(inq,0,sizeof inq); 82             DFS(S,0x3f3f3f3f); 83         } 84     } 85     return; 86 } 87 int main(){ 88     int i,j,w; 89     m=read();n=read(); 90     S=0;T=n+m*n+1; 91     for(i=1;i<=n;i++){ 92         insert(S,i,1,0); 93     } 94     for(i=1;i<=n;i++){ 95         for(j=1;j<=m;j++){ 96             w=read(); 97             for(int k=1;k<=n;k++){ 98                 insert(i,j+n+m*(k-1),1,w*k); 99             }100         }101     }102     for(i=1;i<=m;i++)103         for(j=1;j<=n;j++)104             insert(i+n+m*(j-1),T,1,0);105     mxflow(S,T);106     printf("%.2f\n",(double)ans/n);107     return 0;108 }

 

Bzoj1070 [SCOI2007]修车