[BZOJ1070][SCOI2007]修车 费用流

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1070

这种资源分配,平衡下最优解的题目好多都可以建图跑。要把车分配给修车师傅这种模式,想到网络流,又因为要修的车数N不会变,相当于总流量固定,则考虑费用流。但是直接考虑师傅修车是不好做的,我们反过来考虑车被师傅修,接下来就是神奇的建图。

考虑车对答案的贡献,假设第i个车是第j个师傅修的倒数第k个车,于是它的贡献就是Ti[i][j]*k。

然后考虑第i个车对可能的情况连边,xjb建一建就出来了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 const int INF=1<<30;
 7 int inline readint(){
 8     int Num;char ch;
 9     while((ch=getchar())<'0'||ch>'9');Num=ch-'0';
10     while((ch=getchar())>='0'&&ch<='9') Num=Num*10+ch-'0';
11     return Num;
12 }
13 int N,M;
14 int Ti[65][15];
15 int S,T;
16 int to[100000],ne[100000],c[100000],w[100000],fir[1000],cnt=0;
17 void add(int a,int b,int x,int y){
18     to[cnt]=b,c[cnt]=x,w[cnt]=y,ne[cnt]=fir[a],fir[a]=cnt++;
19     to[cnt]=a,c[cnt]=0,w[cnt]=-y,ne[cnt]=fir[b],fir[b]=cnt++;
20 }
21 int dis[1000],pre[1000];
22 bool in[1000];
23 queue <int> q;
24 bool spfa(){
25     memset(dis,127/3,sizeof(dis));
26     dis[S]=0;
27     in[S]=true;
28     q.push(S);
29     int u;
30     while(!q.empty()){
31         u=q.front();
32         q.pop();
33         in[u]=false;
34         for(int i=fir[u];i!=-1;i=ne[i]){
35             int v=to[i];
36             if(dis[v]>dis[u]+w[i]&&c[i]){
37                 dis[v]=dis[u]+w[i];
38                 pre[v]=i;
39                 if(!in[v]){
40                     q.push(v);
41                     in[v]=true;
42                 }
43             }
44         }
45     }
46     return dis[T]!=dis[0];
47 }
48 int Mcmf(){
49     int cost=0;
50     pre[S]=-1;
51     while(spfa()){
52         int f=INF;
53         for(int i=pre[T];i!=-1;i=pre[to[i^1]]) f=min(f,c[i]);
54         for(int i=pre[T];i!=-1;i=pre[to[i^1]]){
55             c[i]-=f;
56             c[i^1]+=f;
57         }
58         cost+=f*dis[T];
59     }
60     return cost;
61 }
62 int main(){
63     M=readint();
64     N=readint();
65     for(int i=1;i<=N;i++)
66         for(int j=1;j<=M;j++)
67             Ti[i][j]=readint();
68     memset(fir,-1,sizeof(fir));
69     S=(M+1)*N+1;
70     T=(M+1)*N+2;
71     for(int i=1;i<=N;i++) add(S,N*M+i,1,0);
72     for(int i=1;i<=N*M;i++) add(i,T,1,0);
73     for(int i=1;i<=N;i++)
74         for(int j=1;j<=M;j++)
75             for(int k=1;k<=N;k++)
76                 add(N*M+i,(j-1)*N+k,1,Ti[i][j]*k);
77     printf("%.2lf\n",(double)Mcmf()/N);
78     return 0;
79 }

 

posted @ 2017-09-24 21:48  halfrot  阅读(143)  评论(0编辑  收藏  举报