1070. [SCOI2007]修車【費用流】
阿新 • • 發佈:2018-03-31
med tdi lib 逆向 node void input size 小數點
2 2
3 2
1 4
Description
同一時刻有N位車主帶著他們的愛車來到了汽車維修中心。維修中心共有M位技術人員,不同的技術人員對不同
的車進行維修所用的時間是不同的。現在需要安排這M位技術人員所維修的車及順序,使得顧客平均等待的時間最
小。 說明:顧客的等待時間是指從他把車送至維修中心到維修完畢所用的時間。
Input
第一行有兩個m,n,表示技術人員數與顧客數。 接下來n行,每行m個整數。第i+1行第j個數表示第j位技術人
員維修第i輛車需要用的時間T。
Output
最小平均等待時間,答案精確到小數點後2位。
Sample Input
3 2
1 4
Sample Output
1.50HINT
數據範圍: (2<=M<=9,1<=N<=60), (1<=T<=1000)
將M個工作人員拆成N個點
拆後的M員工的第k個裂點連某輛車,表示該車是倒數第k個被修的車
因為是倒數第k,所以費用自然要加上後面排隊的車的費用
算是一種逆向思維吧
MD n和m搞反了……找錯找了半天qwq
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<queue> #define MAXN (50000+10) #define MAXM (5000000+10) using namespace std; queue<int>q; bool visit[MAXN]; int pre[MAXN]; int n,m,k,s,e=4999,Ans,Fee; int num_edge; int head[MAXN]; int dis[MAXN]; bool used[MAXN]; int INF; int t[1000][1000]; struct node { int to; int next; int Flow;//殘留網絡 int Cost; } edge[MAXM*2]; void add(int u,int v,int l,int c) { edge[++num_edge].to=v; edge[num_edge].next=head[u]; edge[num_edge].Flow=l; edge[num_edge].Cost=c; head[u]=num_edge; } bool Spfa(int s,int e) { memset(pre,-1,sizeof(pre)); memset(dis,0x7f,sizeof(dis)); q.push(s); dis[s]=0; used[s]=true; while (!q.empty()) { int x=q.front(); q.pop(); for (int i=head[x]; i!=0; i=edge[i].next) if (dis[x]+edge[i].Cost<dis[edge[i].to] && edge[i].Flow>0) { dis[edge[i].to]=edge[i].Cost+dis[x]; pre[edge[i].to]=i; if (!used[edge[i].to]) { used[edge[i].to]=true; q.push(edge[i].to); } } used[x]=false; } return (dis[e]!=INF); } int MCMF(int s,int e) { Ans=0,Fee=0; while (Spfa(s,e)) { int d=INF; for (int i=e; i!=s; i=edge[((pre[i]-1)^1)+1].to) d=min(d,edge[pre[i]].Flow); for (int i=e; i!=s; i=edge[((pre[i]-1)^1)+1].to) { edge[pre[i]].Flow-=d; edge[((pre[i]-1)^1)+1].Flow+=d; } Ans+=d; Fee+=d*dis[e]; } return Fee; } int main() { memset(&INF,0x7f,sizeof(INF)); scanf("%d%d",&m,&n); for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) scanf("%d",&t[i][j]); for (int i=1;i<=m*n;++i) { add(s,i,1,0); add(i,s,0,0); } for (int i=1;i<=n;++i) { add(m*n+i,e,1,0); add(e,m*n+i,0,0); } for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) for (int k=1;k<=n;++k) { add((j-1)*n+i,m*n+k,1,i*t[k][j]); add(m*n+k,(j-1)*n+i,0,-i*t[k][j]); } double ans=MCMF(s,e); printf("%.2lf\n",ans/n); }
1070. [SCOI2007]修車【費用流】